Указатели

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

Копировать
тип *имя_переменной

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

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

Копировать
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;