Учебники

C — указатели

Указатели на C легки и интересны для изучения. Некоторые задачи программирования на Си легче выполняются с помощью указателей, а другие задачи, такие как динамическое распределение памяти, не могут быть выполнены без использования указателей. Поэтому становится необходимым изучать указатели, чтобы стать идеальным программистом Си. Давайте начнем изучать их в простых и легких шагах.

Как вы знаете, каждая переменная является ячейкой памяти, и каждая ячейка памяти имеет свой адрес, к которому можно обратиться, используя оператор амперсанда (&), который обозначает адрес в памяти. Рассмотрим следующий пример, который печатает адрес определенных переменных:

Live Demo

#include <stdio.h>

int main () {

   int  var1;
   char var2[10];

   printf("Address of var1 variable: %x\n", &var1  );
   printf("Address of var2 variable: %x\n", &var2  );

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Address of var1 variable: bff5a400
Address of var2 variable: bff5a3f6

Что такое указатели?

Указатель — это переменная, значением которой является адрес другой переменной, т. Е. Прямой адрес ячейки памяти. Как и любая переменная или константа, вы должны объявить указатель, прежде чем использовать его для хранения любого адреса переменной. Общая форма объявления переменной указателя —

type *var-name;

Здесь тип — это базовый тип указателя; это должен быть допустимый тип данных C, а var-name — это имя переменной-указателя. Звездочка *, используемая для объявления указателя, такая же, как звездочка, используемая для умножения. Однако в этом утверждении звездочка используется для обозначения переменной в качестве указателя. Взгляните на некоторые из допустимых объявлений указателей —

int    *ip;    /* pointer to an integer */
double *dp;    /* pointer to a double */
float  *fp;    /* pointer to a float */
char   *ch     /* pointer to a character */

Фактический тип данных значения всех указателей, будь то целое число, число с плавающей запятой, символ или другое, является одним и тем же, длинное шестнадцатеричное число, представляющее адрес памяти. Единственное различие между указателями разных типов данных — это тип данных переменной или константы, на которую указывает указатель.

Как использовать указатели?

Есть несколько важных операций, которые мы будем делать с помощью указателей очень часто. (а) мы определяем переменную указателя, (б) назначаем адрес переменной указателю и (в) наконец получаем доступ к значению по адресу, доступному в переменной указателя. Это делается с помощью унарного оператора *, который возвращает значение переменной, расположенной по адресу, указанному ее операндом. В следующем примере используются эти операции —

Live Demo

#include <stdio.h>

int main () {

   int  var = 20;   /* actual variable declaration */
   int  *ip;        /* pointer variable declaration */

   ip = &var;  /* store address of var in pointer variable*/

   printf("Address of var variable: %x\n", &var  );

   /* address stored in pointer variable */
   printf("Address stored in ip variable: %x\n", ip );

   /* access the value using the pointer */
   printf("Value of *ip variable: %d\n", *ip );

   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

Address of var variable: bffd8b3c
Address stored in ip variable: bffd8b3c
Value of *ip variable: 20

NULL указатели

Хорошей практикой всегда является присвоение значения NULL переменной-указателю, если у вас нет точного адреса для назначения. Это делается во время объявления переменной. Указатель, которому присвоен NULL, называется нулевым указателем.

Указатель NULL — это константа со значением ноль, определенная в нескольких стандартных библиотеках. Рассмотрим следующую программу —

Live Demo

#include <stdio.h>

int main () {

   int  *ptr = NULL;

   printf("The value of ptr is : %x\n", ptr  );
 
   return 0;
}

Когда приведенный выше код компилируется и выполняется, он дает следующий результат —

The value of ptr is 0

В большинстве операционных систем программам не разрешен доступ к памяти по адресу 0, поскольку эта память зарезервирована операционной системой. Однако адрес памяти 0 имеет особое значение; он сигнализирует о том, что указатель не предназначен для указания на доступную ячейку памяти. Но по соглашению, если указатель содержит нулевое (нулевое) значение, предполагается, что он ничего не указывает.

Чтобы проверить нулевой указатель, вы можете использовать оператор if следующим образом:

if(ptr)     /* succeeds if p is not null */
if(!ptr)    /* succeeds if p is null */

Указатели в деталях

У указателей есть много, но простых концепций, и они очень важны для программирования на Си. Следующие важные концепции указателей должны быть понятны любому программисту C —

В указателях можно использовать четыре арифметических оператора: ++, -, +, —

Вы можете определить массивы для хранения нескольких указателей.

C позволяет вам иметь указатель на указатель и так далее.

Передача аргумента по ссылке или по адресу позволяет вызывающему функции изменять переданный аргумент в вызывающей функции.

C позволяет функции возвращать указатель на локальную переменную, статическую переменную и динамически выделенную память.