Связь с указателями. Пример
По определению операция индексирования «[]» интерпретируется так, что e1[e2] эквивалентно *((e1) + (e2)). Здесь внутренние скобки указывают, что вначале выполняются все операции внутри e1 и e2, затем + и затем *. Если e1 имя массива и e2 значение целого типа, то выражение выполняется в соответствии с правилами адресной арифметики, т.е. с учетом типа.
Пример
float a[20];
……………………..
…a[5]…..
Если a соответствует адресу, например, 100, то a[5] извлекает 4 байта, расположенных с адреса 100 + 5*4 = 120.
Если е - многомерный массив и задано в определении:
тип е[n1][n2]…[nm]; и если е появляется где-либо в выражении, то эта запись преобразовывается в адрес самого первого элемента массива, что эквивалентно записи &e[0][0]…[0] (индексы повторяются m раз).
Запись вида e[i] преобразуется в ссылку на (m-1) – мерный массив, а именно:
e[i] эквивалентно записи (e + i), что в результате дает адрес равный:
e + i xn2 x…xnm x sizeof(тип).
Фактически это эквивалентно записи:
&e[i][0]…[0] (0-е индексы повторяются m-1раз)
Добавим еще один индекс, чтобы понять принцип расчета. Запись в выражении вида e[i][j] преобразуется в ссылку на (m-2) мерный массив, что дает адрес равный:
e + i x n2 x… x nm xsizeof(тип)+j x n3 x… x nm x sizeof(тип)
И это эквивалентно записи :
&e[i][j][0]…[0] (0-й индекс повторяется m-2 раз).
Исчерпание всех индексов означает получение доступа к 0-мерному массиву и это конкретное значение в ячейке, а не адрес.
Пример
float array[2][5];
Указанные записи в выражениях эквивалентны:
1) array, &array[0][0]
2) array[i], (array+i).
Эффективность доступа через индексы и через указатели приблизительно одинакова, но в последнем случае программа иногда короче и в ряде случаев можно обойтись без дополнительных переменных.
Пример
Обоснованный пример использования указателей вместо индексов. Выделяется память по запросам – функция alloc(n) //n – запрашивающий размер; функция free(p) – освобождает память, на которую ссылается указатель.
#define NULL 0 /*значение ошибки*/
#define ALLOCSIZE 100/*объем доступной памяти*/
static char allocbuf[ALLOCSIZE];/* непрерывная память*/
static char *allocp=allocbuf;/*указатель на свободное место*/
char *alloc(n) /*выдача сc на n байт*/
int n;
{ if (allocp+n<=allocbuf+ALLOCSIZE){ /* ?есть место*/
allocp+=n;
return (allocp-n);
} else return (NULL); /*места нет*/
}
free(p); /*возврат памяти сс р*/
char *p;
{
if (p>=allocbuf&&p<allocbuf+ALLOCSIZE)
allocp=p;
}
Такая программа может работать правильно, если возвращается всегдапоследовательный выделенный кусок памяти.
Проверки вида if(allocp+n<=allocbuf+ALLOCSIZE) “хватит ли места для запроса” и if(p>=allocbuf&&p<allocbuf+ALLOCSIZE) “попадание ссылки в заданный диапазон” для указателей будут выполняться правильно, если ссылки формируются относительно общего базового адреса, в данном случае это один и тот же массив. Мы не рассматриваем особенности сравнения указателей для различных их модификаций с учетом моделей памяти.
Дата добавления: 2016-05-26; просмотров: 1419;