Справочник по C/C++
Указатели

Указатель — это переменная, которая содержит адрес некоторого объекта. Здесь имеется в виду адрес в памяти компьютера. Указатели определяются следующим образом.

тип *имя_переменной

С указателями связано два оператора:

  • &
  • — взятие адреса
  • *
  • — возврат значения по указанному адресу

Рассмотрим пример кода.

int x=10;
int *p, *g;	//определение указателей
p = &x;	//берём адрес переменной x
g = p;	//создаём ещё один указатель который тоже указывает на x
cout << *g;	//печатаем значение переменной x

В языке C возможна ситуация когда указатели ссылаются на указатели. Например.

int **point;
Указатель Указатель Переменная
Адрес    --->       Адрес    --->       Значение
Соответственно чтобы получить значение переменной, необходимо написать: **point.

Инициализация указателей

После того как указатель был объявлен, но до того как ему было присвоено какое либо значение, указатель содержит неизвестное значения. Поэтому попытка использовать указатель до присвоения ему значения является неприятной ошибкой, так как она может нарушить работу программы но и системы. Обычно в таких случаях система, если не зависает, выдаёт сообщение: "Null pointer assignement".

Принято считать, что указатель, который указывает в никуда должен иметь значение null или 0.

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

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

int *p, x;
p = &x;
p++;	//увеличиваем значение расположеное по адресу p
В этом примере p увеличиться не на 1, а на 2, т.к. x носит переменную типа int. И это правильно т.к. новое значение должно указывать не на следующий адрес в памяти, а на адрес следующего целого.

Над указателем можно применять основные операции сравнения. Например p < g означает что адрес находящийся в p меньше адреса находящегося в g

Общая формула для вычисления значения указателя после выполнения операции сложения следующая: p = p+n*киличество_байт_памяти_базового_типа_указателя, где p — указатель, n — число, на которое происходит увеличение.

Преобразование типов в указателях

Если указатель определён одним типом, а переменная, на которую он будет указывать другого типа то необходимо, перед присваиванием адреса, обязательно выполнять преобразование типов.

float int;
int *p;
p = (int*)&x;
При подобных присвоениях необходимо следить за размерами переменных. Если переменная с более длинного типа будет преобразовываться на тип с меньшими размерами, то значение переменной будет урезаться. Например, предыдущий код будет неверен, так как истинное значение переменной теряется (float = 4 байтам, а int = 2 байта).

Тип void и указатели

Нельзя создавать переменную типа void, но можно создавать указатель на тип void. Указателю на void можно присвоить указатель любого другого типа. Однако при обратном присваивании необходимо использовать явное преобразование указателя на void.

void *pv;
float f, *pf;
pf = &f;
pv = pf;
pf = (float*)pv;

Массивы и указатели

В языке C существует связь между указателями и массивами. Имя массива — это адрес памяти, с которого расположен массив, т.е. адрес первого элемента массива. Например.

int plus[10];
Здесь переменная plus является указателем на массив, точнее на первый элемент массива. Следующие две операции идентичны.
p = plus;
p = &plus[0];

Арифметические операции над указателями выполняются быстрее, чем над массивами, если мы работаем с подряд идущими элементами. Например, в следующих двух идентичных записях, где происходит ссылка на 6-й элемент массива, второй вариант предпочтительнее.

plus[5];
*(plus+5);

Для динамического выделения памяти, во время работы программы, под массив используется оператор new, например.

int *a = new int[N];
if (a == 0) {cout << "out of memory" << endl; rturn 0;}
Также память можно выделять и под многомерные массивы, например.
int **malloc2d (int r, int c){
	int **t= new int*[r];
	for (int i = 0; i < r; i++)
		t[i] = new int[c];
	return t;
}

int *a = malloc2d (M*N*sizeof(int));
приведённый выше код создаст массив как массив указателей на массивы. После создания переменной с помощью созданной функции будет возможность ссылаться на элемент массива как a[i][j].

Строки и указатели

Строчная константа в языке C ассоциируется с адресом начала строки в памяти, тип строки получается char* (указатель на тип char). Поэтому возможно, активно использовать следующее присваивание.

char *pc;
pc = "Hello world";

Строки заканчиваются нулевым значением (0) ,поэтому следующий пример напечатает всю строку по символу.

while (*str++) cout<<str;



Реклама