Difference between revisions of "Basic Pascal Tutorial/Chapter 5/Pointers/bg"

From Lazarus wiki
Jump to navigationJump to search
(Created page with "{{Basic Pascal Tutorial/Chapter 5/Pointers}} {{TYNavigator|Chapter 5/Records|Chapter 6/Final words}} == 5F - Указатели == ''(author: Tao Yue, state: unchanged)'' [...")
 
Line 39: Line 39:
  
 
На един указател може да се присвои стойността на друг указател.
 
На един указател може да се присвои стойността на друг указател.
Имайте предвид обаче, че тъй като се копира само '''адресът''', а не стойността, след като промените данните, намиращи се в един указател, другият указател, когато се дереферира, също дава променените данни.
+
Имайте предвид обаче, че тъй като се копира само '''адресът''', а не стойността, след като промените данните, намиращи се в един указател, другият указател също сочи към променените данни.
 
Освен това, ако освободите заетата памет за указател, копираният указател вече сочи към безсмислени данни.
 
Освен това, ако освободите заетата памет за указател, копираният указател вече сочи към безсмислени данни.
  
== Trivial usage example: singly linked lists ==
+
== Пример за употреба: единично свързани списъци ==
 +
За какво е добре да се използват указателите?
 +
Не може ли просто в примерите по-горе да се използват целочислени променливи вместо указателите към тях?
 +
Очевидно горните примери са измислени само с демонстрационна цел.
 +
Истинската сила на указателите е, че когато се комбинират със записи, тогава е възможно да се създават динамични структури от данни.
 +
Когато има нужда да се помнят много данни от един тип в някакъв порядък, тогава може да се използва масив. 
 +
Вашият масив обаче има предварително зададен размер. Ако той не е достатъчно голям, може да не успеете да поберете всички данни или обратно - ако имате огромен масив заемате много памет която не се използва.
  
What is a pointer good for?
+
Динамичната структура на данни, от друга страна, заема само толкова памет, колкото е необходимо. Това, което трябва да направите, е да създадете тип данни, който сочи към запис. След това записът има този тип указател като едно от своите полета. напр. всички стекове и опашки могат да бъдат реализирани с помощта на следната структура от данни:
Why can't you just use an integer in the examples above instead of a pointer to an integer?
 
Well, the above is clearly a contrived example.
 
The real power of pointers is that, in conjunction with records, it makes dynamically-sized data structures possible.
 
If you need to store many items of one data type in order, you can use an array.
 
However, your array has a predefined size.
 
If you don't have a large enough size, you may not be able to accomodate all the data.
 
If you have a huge array, you take up a lot of memory when sometimes that memory is not being used.
 
 
 
A dynamic data structure, on the other hand, takes up only as much memory as is being used.
 
What you do is to create a data type that points to a record.
 
Then, the record has that pointer type as one of its fields.
 
E. g. stacks and queues can all be implemented using this data structure:
 
 
<syntaxhighlight lang=pascal>
 
<syntaxhighlight lang=pascal>
 
type
 
type
Line 66: Line 60:
 
</syntaxhighlight>
 
</syntaxhighlight>
  
Each element points to the next.
+
Всеки запис сочи към следващия с полето си ''next''.
The last record in the chain indicates that there is no next record by setting its next field to a value of <tt>nil</tt>.
+
Последният запис във веригата има в полето ''next'' специалната стойност <tt>nil</tt>.
  
 
{{TYNavigator|Chapter 5/Records|Chapter 6/Final words}}
 
{{TYNavigator|Chapter 5/Records|Chapter 6/Final words}}

Revision as of 16:49, 3 January 2023

български (bg) English (en) français (fr) 日本語 (ja) 中文(中国大陆)‎ (zh_CN)

 ◄   ▲   ► 

5F - Указатели

(author: Tao Yue, state: unchanged)

Указателя е тип данни, който съдържа адрес в паметта. Указателят може да се разглежда като препратка към този адрес, докато променливата е просто друго име за този адрес. Ако променливата съдържа нечий телефонен номер, то тогава указателят е страницата и номерът на реда, където е изписан номера в телефонния указател. За да получите достъп до данните, съхранени на този адрес в паметта, трябва да 'последвате' стойността на указателя.

Резервиране на памет

За да декларирате указател, трябва да укажете към какво ще сочи той. Типът данни към който ще сочи се предхожда от стрелка (^). Например, ако декларирате указател към цяло число, ще трябва да използвате следния код:

type
  PointerType = ^integer;

След това можете да декларирате променливи от типа PointerType.

Преди да използвате указател, трябва да запазите място в паметта за променливата към която той ще сочи. Това се прави с:

New(PointerVariable);

За да достъпите данните към които сочи указателя, трябва да добавите стрелка след името му. Например, ако PointerVariable е декларирана като PointerType (по-горе), можете да присвоите стойност на мястото в паметта, като използвате:

PointerVariable^ := 5;

След като приключите с указателя, трябва да освободите пространството в паметта. В противен случай, всеки път, когато програмата се стартира, тя ще запазва все повече и повече памет, докато накрая компютърът ви няма повече такава. За да освободите заетата памет, трябва да използвате командата Dispose:

Dispose(PointerVariable);

На един указател може да се присвои стойността на друг указател. Имайте предвид обаче, че тъй като се копира само адресът, а не стойността, след като промените данните, намиращи се в един указател, другият указател също сочи към променените данни. Освен това, ако освободите заетата памет за указател, копираният указател вече сочи към безсмислени данни.

Пример за употреба: единично свързани списъци

За какво е добре да се използват указателите? Не може ли просто в примерите по-горе да се използват целочислени променливи вместо указателите към тях? Очевидно горните примери са измислени само с демонстрационна цел. Истинската сила на указателите е, че когато се комбинират със записи, тогава е възможно да се създават динамични структури от данни. Когато има нужда да се помнят много данни от един тип в някакъв порядък, тогава може да се използва масив. Вашият масив обаче има предварително зададен размер. Ако той не е достатъчно голям, може да не успеете да поберете всички данни или обратно - ако имате огромен масив заемате много памет която не се използва.

Динамичната структура на данни, от друга страна, заема само толкова памет, колкото е необходимо. Това, което трябва да направите, е да създадете тип данни, който сочи към запис. След това записът има този тип указател като едно от своите полета. напр. всички стекове и опашки могат да бъдат реализирани с помощта на следната структура от данни:

type
	PointerType = ^RecordType;
	RecordType = record
		data : integer;
		next : PointerType;
	end;

Всеки запис сочи към следващия с полето си next. Последният запис във веригата има в полето next специалната стойност nil.

 ◄   ▲   ►