[С++ ]

Вказівни́к  Значення вказівника посилається на інше значення, що записане будь-де в пам'яті комп'ютера (фактично містить його адресу).

Мови програмування, в яких передбачений тип вказівник, містять, як правило, дві основні операції над ними: присвоювання і розіменування. Операція присвоювання записує в значення вказівника певну адресу в пам'яті комп'ютера.

Розіменування вказівника

Операція отримання значення, на яке посилається вказівник, називається розіменування вказівника.

У мові програмування С++:

double A = 5; /*декларація дійсної змінної подвійної точності */
double *a; /*декларація вказівника на дійсну змінну */
a = &A; /* присвоєння вказівнику адреси змінної A. a тепер вказує на A */
*a = 10; /*Присвоєння значення тому, на що вказує а. *a — операція розіменування вказівника */

a є вказівником на число типу double*a — розіменування вказівника. У результаті змінна A отримує значення 10.

Нульовий вказівник

Нульовий вказівник — це вказівник, який нікуди не вказує. Використовується для того, щоб показати, що дана зміна-вказівник ні на що не посилається. У різних мовах програмування представлений різними константами.

Вказівники описуються операторами виду:

<тип> - це будь-який, допустимий в С++ тип даних; * Зірочка говорить про те, що наступний за нею <об'єкт> є об'єктом, що вказує на дане <тип>; <об'єкт> у найпростішому випадку це <ідентифікатор> і тоді він являє собою скалярную змінну, яка є покажчиком.
Під адресному арифметикою розуміються дії над вказівниками, пов'язані з використанням адрес пам'яті. 
1. Присвоювання. Вказівник можна присвоїти значення адреси. Будь-яке число, присвоєне вказівником, трактується як адреса пам'яті
int *u,*adr;
int N;
u = &N; //Вказівнику присвоєна адреса Н 

2. Взяття адреси. Так як вказівник є змінною, то для отримання адреси пам'яті, де розташований вказівник, можна використовувати операцію взяття адреси &:

int *a,*b;
a = &b; //Взяли адресу вказівника b

3. Непряма адресація. Для того, щоб отримати значення, що зберігається за адресою, на який посилається вказівник, або послати дані за адресою, використовується операція непрямої адресації *:

int *uk;
int n;
int m = 5;
uk = &m; // uk присвоює адресу змінної m 
n = *uk; // змінна n приймає значення 5 
*uk = -13; // змінна m приймає значення -13

 

 

 

 

 

4. Преобразование типа. Указатель на объект одного типа может быть преобразован в указатель на другой тип. При этом следует учитывать, что объект, адресуемый преобразованным указателем, будет интерпретироваться по-другому. Операция преобразования типа указателя применяется в виде (<тип> *)<указатель> :

int i, *ptr;
i = 0x8e41;
ptr = &i;
printf("%d\n", *ptr); // печатается значение int:-29119 (0x8e41)
printf("%d\n", *((char *)ptr)); // ptr преобразован к типу сhar, 
 // извлекается 1 байт и его двоичный код
 // печатается в виде десятичного числа,  
 // печатается: 65 */

Преобразование типа указателя чаще всего применяется для приведения указателя на неопределенный тип данных void к типу объекта, доступ к которому будет осуществляться через этот указатель.

5. Определение размера. Для определения размера указателя можно использовать операцию размер в виде sizeof(<указатель>). Размер памяти, отводимой компилятором под указатель, зависит от модели памяти. Для близких указателей операция sizeof дает значение 2, для дальних 4.

6. Сравнение. Сравнение двух указателей любой из операций отношения имеет смысл только в том случае, если оба указателя адресуют общий для них объект, например, строку или массив.

7. Индексация. Указатель может индексироваться применением к нему операции индексации, обозначаемой в Си квадратными скобками [ ]. Индексация указателя имеет вид<указатель>[<индекс>], где <индекс> записывается целочисленным выражением.

Возвращаемым значением операции индексации является данное, находящееся по адресу, смещенному в б?льшую или меньшую сторону относительно адреса, содержащегося в указателе в момент применения операции. Этот адрес определяется так: (адрес в указателе) + (значение <индекс>) * sizeof(<тип>), где <тип> – это тип указателя.

Из этого адреса извлекается или в этот адрес посылается, в зависимости от контекста применения операции, данное, тип которого интерпретируется в соответствии с типом указателя. Рассмотрим следующий пример:

int *uk1;
int b,k;
uk1 = &b; // в uk1 адрес переменной b 
k = 3;
b = uk1[k]; // переменной b присваивается значение int, 
 // взятое из адреса на 6 большего, чем 
 // адрес переменной b; в uk1 адрес не изменился
uk1[k] = -14; // в адрес на 6 больший, чем адрес переменной b, 
 // записывается -14

Операция индексации не изменяет значение указателя, к которому она применялась.

8. Увеличение/уменьшение. Если к указателю применяется операция увеличения ++ или уменьшения --, то значение указателя увеличивается или уменьшается на размер объекта, который он адресует:

long b; // b – переменная типа int длиной 4 байта 
long *ptr; // ptr – указатель на объект int длиной 4 байта
ptr = &b; // в ptr адрес переменной b 
ptr++; // в ptr адрес увеличился на 4 
ptr--; // в ptr адрес уменьшился на 4

9. Сложение. Одним из операндов операции сложения может быть указатель, а другим операндом обязательно должно быть выражение целого типа. Операция сложения вырабатывает адрес, который определяется следующим образом:  (адрес в указателе) + (значение int_выражения)*sizeof(<тип>), где <тип> это тип данных, на которые ссылается указатель.

double d;
int n;
double *uk;
uk = &d; // в uk адрес переменной d 
n = 3;
uk = uk+n; // в результате выполнения операции сложения, 
 // а затем операции присваивания, в uk новый 
 // адрес на 24 больше, чем предыдущий 
uk=n+uk; // в uk адрес увеличился еще на 24

10. Вычитание. Левым операндом операции вычитания должен быть указатель, а правым должно быть выражение целого типа. Операция вычитания вырабатывает адрес, который определяется так: (адрес в указателе) - (значение int_выражения)*sizeof(<тип>).

К указателям можно применять только описанные операции и операции, которые выражаются через них, например, разрешается к указателю применить операцию uk += n; , так как ее можно выразить через uk = uk+n; . Следующие операции недопустимы с указателями:

  • сложение двух указателей;
  • вычитание двух указателей на различные объекты;
  • сложение указателей с числом с плавающей точкой;
  • вычитание из указателей числа с плавающей точкой;
  • умножение указателей;
  • деление указателей;
  • поразрядные операции и операции сдвига;
: