Указатели и массивы очень тесно связаны между собой. Как объяснялось ранее, имя массива без индекса - это указатель на первый элемент массива. Пусть имеется массив
	
	char р [10];
	
	тогда следующие операторы идентичны:
	
	р
	&р [0]
	
	Выражение
	
	р == &р [0]
	
	выдает истину, поскольку адрес первого элемента и адрес массива совпадают.
	Справедливо и обратное. Любой указатель может быть проиндексирован, как будто это массив. Например:
	
	int *р, i [10];
	p = i;
	р[5] = 100; /* присвоение с помощью индекса */
	*(р+5) = 100; /* присвоение с помощью арифметики с указателями */
	
	Оба оператора присваивания помещают значение 100 в шестой элемент i. Первый оператор использует индексацию с р, а второй - арифметику указателей. Так или иначе, результат одинаков.
	Данные способы индексации совершенно справедливы для массивов размерности 2 и более. Предположим, что а - это целочисленный массив 10 на 10. Тогда нижеприведенные операторы эквивалентны:
	
	а
	&а [0] [0]
	
	Более того, к элементу 0, 4 массива а можно обратиться или с помощью индексации массива -а[0][4], или с помощью указателя — *((int *) а + 4). Аналогично к элементу 1, 2 можно обратиться или с помощью индексации массива - а [1] [2], или с помощью указателя - *((int *) а + 12). В целом, для любого двумерного массива справедливо
	
	а[j][k] эквивалентно *((тип *) a + (j * длина строки) + k)
	
	где тип - это базовый тип массива.
Указатели иногда используются для обращения к массивам, поскольку арифметика указателей чаще всего выполняется быстрее, чем индексация массивов. Преимущество - скорость использования указателей - наиболее заметно, когда осуществляется последовательный доступ к массиву. В данной ситуации указатель может увеличиваться или уменьшаться с помощью эффективных операторов увеличения или уменьшения. С другой стороны, если доступ к массиву происходит случайным образом, то лучше использовать индексацию массива, а не указатели.
Двумерные массивы подобны массивам указателей на строки. Поэтому использование отдельных указателей является одним из легких способов доступа к элементам двумерного массива.
	Следующая функция демонстрирует данный прием. Она выводит содержимое указанной строки глобального целочисленного массива num:
	
	int num [10][10];
	void pr_row (int j )
	{
	int *p, t;
	p = num [ j]; /* получение адреса первого элемента строки j */
	for(t=0; t<10; ++t) printf("%d ",(p+t) );
	}
	
	Данный код может быть обобщен, если передавать в качестве аргументов строку, длину строки и указатель на первый элемент массива:
	
	/* общий */
	void pr_row(int j, int row_dimension, int *p)
	{
	int t;
	p = p + (j * row_dimension);
	for(t=0; t<row_dimension; ++t)
	printf("%d ", *(p+t));
	}
С массивами, имеющими размерность более чем 2, можно поступать аналогичным образом. Например, трехмерный массив может быть упрощен до указателя на двумерный массив, который в свою очередь может быть упрощен до указателя на одномерный массив. В общем случае N-мерный массив может быть упрощен до указателя на (N-1)-мерный массив. Данный новый массив может быть аналогичным образом упрощен. Этот процесс продолжается, пока не получится одномерный массив.
