Работа с указателями на Си

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

  • «*» — операция разыменования указателя (будучи примененной к указателю, возвращает значение объекта, на который он указывает),  «*» так же используется для объявлений указателей.
  • «&» — операция взятия адреса (применяется к объектам для взятия их адреса с тем, чтобы записать его в указатель).
// объявили два указателя на целочисленные объекты,
// объявили две целочисленные переменные,
// объявили указатель на строку и указатель на любой тип.
int *a, *b, c=10, d, char *s, void *f;

// в указатель а записали адрес объекта c
a=&c;

// объекту d приравняли значение объекта,
// адрес которого содержится в указателе a.
// Эти две строки равносильны строке d=c.
d=*a;

// сначала напечатается число 10
// (значение объекта, на который ссылается указатель),
// а затем адрес памяти
printf("%d %p", *a, a);

Так же можно конструировать и объявлять сложные виды указателей, например:

// объявили массив из 10 элементов типа "указатель на int".
// Это равнозначно записи int *x[10]
int*(x[10]);

// объявили указатель на массив из 10 элементов целочисленного типа.
int (*x)[10];

// объявили прототип функции f без параметров,
// возвращающей значение типа "указатель на массив из 10 элементов типа int"
int (*f())[10];

Операции с указателями

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

Указатели и массивы

При объявлении массива, например, int a[10]; , так же автоматически объявляется переменная-указатель типа int, причем этот указатель указывает на нулевой элемент этого массива:

// объявили указатель на тип int
int *pt; 

// объявили массив из 25 целых чисел, при это автоматически объявляется 
// переменная int *arr, указывающая на начальный элемент массива
int arr[25]; 

// в указатель pt записали адрес начального элемента массива
pt=&arr[0]; 

// мы увидим два одинаковых числа.
printf("%p t %p",arr, pt); 

Обращаться к элементам массива можно при помощи указания индекса либо при помощи указателей. arr[4] вернет 5-й элемент массива arr. Такого же результата можно добиться так: *(arr+4). Взять адрес 5-го элемента можно так же двумя способами: &arr[4] эквивалентно arr+4. Если сравнивать эти варианты с точки зрения скорости работы, то предпочтительнее использовать арифметику указателей. Однако практика показывает, что если надо обращаться к элементам массива по порядку, то лучше использовать индексы, а если в хаотичном порядке — то указатели. Операции ++ и — при работе с массивами сдвигают указатель на один элемент массива вниз или вверх. Например:

// объявили массив целых чисел из 3 элементов, а так же указатель на тип int
int a[3], int *b; 

// заполнили массив числами 1,2,3
a[0]=1; a[1]=2; a[3]=3; 

// в указатель b записал адрес начального элемента массива а 
// (можно было бы написать b=&a[0]), вывели на экран значение объекта, 
// на который указывает b. Напечатается цифра 1.
b=a; printf(%d",*b); 

// значение указателя увеличили на количество байт,
// необходимых для хранения int, теперь b указывает
// на следующий элемент массива. Напечатается цифра 2.
b++; printf(%d",*b); 

// Напечатается цифра 3.
b++; printf(%d",*b); 

// значение указателя уменьшили на количество байт,
// необходимых для хранения int, теперь b указывает
// на предыдущий элемент массива. Напечатается цифра 2.
b--; printf(%d",*b); 

Реклама

Отзывы

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s