Связь с указателями. Пример


По определению операция индексирования «[]» интерпретируется так, что 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 xxnm 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 xx 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;


Поиск по сайту:

Воспользовавшись поиском можно найти нужную информацию на сайте.

Поделитесь с друзьями:

Считаете данную информацию полезной, тогда расскажите друзьям в соц. сетях.
Poznayka.org - Познайка.Орг - 2016-2024 год. Материал предоставляется для ознакомительных и учебных целей.
Генерация страницы за: 0.008 сек.