С указателями можно производить следующие операции:
- присваивания;
- арифметические;
- отношения.
Операция присваивания для указателей аналогична этой операции для других типов данных. В отличии от других типов, при операции присваивания , достаточно, чтобы оба операнда были типа «указатель», но типы этих указателей могут быть различными.
Например:
int a;
int *p=&a, *p1;
*p=8 - значение 8 заносится по адресу р, т.е. значение переменой а=8
р1=р - переменной р1 присваивается р, т.е адрес переменной а
Допустимы арифметические операции:
- сложение с константой (соответственно и +=);
- вычитание константы (соответственно и -=)
- инкремент и декремент (++, --).
Арифметические операции с указателями (сложение с константой, вычитание, инкремент и декремент) автоматически учитывают размер типа величин, адресуемых указателями. Эти операции применимы только к указателям одного типа и имеют смысл в основном при работе со структурами данных, последовательно размещенными в памяти, например, с массивами.
Инкрементперемещает указатель к следующему элементу массива, декремент — к предыдущему. Фактически значение указателя изменяется на величину sizeof(тип).
Если указатель на определенный тип увеличивается или уменьшается на константу, его значение изменяется на величину этой константы, умноженную на размер объекта данного типа.
Пример1:
float f,*pf;
pf=&f;
pf--;
pf+=4;
Пример2:
#include <stdio.h>
#include <conio.h>
Void main()
{
char *s,s1[10];
scanf("%s",s1);
s=s1; //или s=&s1[0];
printf("%c \n",*s);
s+=4;
printf("%c \n",*s);
s++;
printf("%c \n",*s);
s++;
printf("%c",*s);
getche();
}
Операции отношения. Для указателей определяются следующие операции отношения: = =, >=, <=, >,<, !=.
р1==р2 результат 1, если р1 и р2 указывают на один и тот же объект в опер. памяти
р1 >р2 результат 1, если р1 расположен в памяти правее (т.е. с большим адресом)
Одномерные массивы
Массив - совокупность данных, имеющих одинаковые характеристики и размещающихся по порядку в выделенной области памяти. Язык С++ не накладывает ограничений на размерность массива. Нумерация элементов массива всегда начинается с нуля. При описании массива, а также при использовании его отдельных элементов индекс по каждому измерению указывается отдельно в прямоугольных скобках.
В отличие от других алгоритмических языков программирования, после выделения памяти для массива, его имя воспринимается как указатель того типа, к которому отнесены элементы массива. Значением имени массива является адрес его первого элемента.
Определение одномерного массива:
тип имя_массива [константное_выражение];
где имя_массива - идентификатор, константное_выражение определяет количество элементов в массиве.
int array1[10];
При определении массива может выполняться его инициализация, т.е. присвоение конкретных значений его элементам. Список значений элементов массива должен быть заключен в фигурные скобки. Явная инициализация элементов массива разрешена только при его определении и возможна либо с указанием размера массива в квадратных скобках, либо без явного указания. Пример.
char s[]={'h','y','u','p','o'};
int x[4]={2,5,8,12};
Если задан размер массива, то значения, не заданные явно, равны 0. Если размер массива опущен, то он определяется по числу начальных значений.
Для доступа к элементу массива после его имени указывается номер элемента (индекс) в квадратных скобках.
В следующем примере подсчитывается сумма элементов массива.
#include <conio.h>
#include <iostream.h>
Int main()
{
int i, sum;
int marks[] = {3, 4, 5, 4, 4};
for (i = 0, sum = 0; i<5; i++)
sum += marks[i];
cout <<"Сумма элементов: " <<sum;
getche();
}
Для доступа к элементу массива можно пользоваться любым из следующих выражений(здесь а – имя массива, р – указатель на массив а)
Так как имя массива после выделения памяти является указателем, к нему применимы все правила адресной математики, связанной с указателями. Таким образом записи имя_массива[индекс] и *(имя_массива +индекс)эквивалентны. В целом следует отметить, что индекс определяет не номер элемента массива, а его смещение относительно начала (поэтому номер первого элемента массива всегда равен 0).
Инициализация символьных массивов может быть выполнена с помощью строк и с помощью символов. Пример.
char h[]="hello"; или char h[]={'h','e','l','l','o','\0'};
Многомерные массивы.
Массивы могут быть многомерными. Многомерный массив есть массив, элементами которого служат массивы.
Определение многомерного массива:
тип имя_массива[a1][a2]…[aN];
где тип - допустимый тип, имя_массива - идентификатор, N - размерность массива, a1 - количество в массиве элементов размерности N-1 каждый и т.д.
Пример.
int A[5][34];
Переменная A - массив из пяти элементов, каждый из которых состоит из 34 элементов.
Инициализация элементов многомерного массива:
int mass2 [][]={ {1, 1}, (0, 2}, (1, 0} };
int mass2 [3][2]={1, 1, 0, 2, 1, 0};
Начальные значения элементов многомерных массивов в списке инициализации располагаются с учетом порядка расположения в памяти.
Пример.
int A[4][3][5] = {0, 1, 2, 3, 4, 5, 6, 7};
В данном случае начальную инициализацию получили только первые 8 элементов массива.
A[0][0][0]==0;
A[0][0][1]==1;
A[0][0][2]==2;
A[0][0][3]==3;
A[0][0][4]==4;
A[0][1][0]==5;
A[0][1][1]==6;
A[0][1][2]==7;
Если необходимо инициализировать только часть элементов многомерного массива, но они размещены не подряд, вводятся дополнительные фигурные скобки, каждая пара которых выделяет последовательность значений, относящихся к одной размерности. Пример.
Остальные элементы массива явно не инициализируются.
Как и в случае одномерных массивов, доступ к элементам многомерных массивов возможен с помощью индексированных переменных и с помощью указателей. В общем случае для двухмерного массива, например, индексированный элемент a[i][j]соответствует выражению *(*(a+i)+j).