Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
111111111.docx
Скачиваний:
6
Добавлен:
17.04.2019
Размер:
131.57 Кб
Скачать

Вопрос 21

Указатели на указатели.

В языке Си можно описать и переменную типа «указатель на указатель». Это ячейка оперативной памяти, в которой будет храниться адрес указателя на какую либо переменную. Признак такого типа данных – повторение символа «*» перед идентификатором переменной. Количество символов «*» определяет уровень вложенности указателей друг в друга. При объявлении указателей на указатели возможна их одновременная инициализация. Например:

int y=5;

int *p1=&y;

int **pp1=&p1;

int ***ppp1=&pp1;

Теперь присвоим целочисленной переменной y новое значение, например 10. Одинаковое присваивание произведут следующие операции:

y=10; *p1=10; **pp1=10; ***ppp1=10;

Для доступа к области ОП, отведенной под переменную y можно использовать и индексы. Справедливы следующие аналоги:

*p1 p1[0] **pp1 pp1[0][0] ***ppp1 ppp1[0][0][0]

Многомерные массивы

Многомерные массивы отличаются от одномерных только тем, что каждый элемент характеризуется не одним, а двумя или более индексами. Они используются, например, для хранения таблиц (каждый элемент таблицы имеет 2 индекса - № строки и № столбца).

Декларация многомерного массива имеет следующий формат:

тип ID [размер1] [размер2]…[размерN] =

{ {список начальных значений},

{список начальных значений},…

};

Списки начальных значений – атрибут необязательный.

Пример:

int a[3][3]={ {1,2,3}, {4,5,6}, {7,8,9} };

Аналогично, при обращении к конкретному элементу многомерного массива указывается имя массива и затем - последовательно индексы элемента, каждый в квадратных скобках; например:

a[2][1]

a[i+1][k]

Рассмотрим особенности работы с многомерными массивами на конкретном примере двумерного массива (двумерные массивы называют также матрицами):

#include <stdio.h>

void main()

{

int i, j;

int m[3][4] = { { 1, 2, 3, 4}, {11,12,13,14}, {21,22,23,24} };

for (i=0; i<3; i++) {

printf("\n %2d)", i+1);

for (j=0; j<4; j++)

printf(" %3d",m[ i ] [ j ]);

}

}

Результаты работы программы:

    1. 2 3 4

    1. 2 13 14

3)21 22 23 24

Вопрос 22 Связь указателей и массивов.

Идентификатор массива указывает адрес памяти, начиная с которого он расположен, т.е. адрес его первого элемента. Работа с массивами тесно связана с применением указателей.

Пусть объявлен массив a из 5 целочисленных элементов:

int a[5];

a

a[0]

a[1]

a[2]

a[3]

a[4]

4000 4004 4008 4012 4016

Здесь приведено символическое изображение оперативной памяти, выделенной компилятором для объявленного целочисленного массива а[5]. Адрес массива выбирается компилятором в зависимости от размера доступной памяти, наличия других переменных и массивов и др. Для конкретности, здесь положено значение адреса, равное 4000. В реальной программе вместо 4000 может быть другое значение, но относительное положение элементов массива всегда остается постоянным.

В языке С идентифи­каторы массивов считаются константными указателями (т.е. в данном примере а "имеет значение" 4000). Такую константу можно присвоить переменной типа указатель, но нельзя подвергать преобразованиям, например:

int a[5], *q;

q = a; // Правильно - присваивание константы переменной

a = q; // Ошибка: в левой части - указатель-константа

Именно потому, что имена массивов считаются константными указателями, в языке Си нельзя непосредственно присваивать массивы друг другу (хотя структуры, включающие массивы как поля, целиком присваивать друг другу можно!)

Однако операция sizeof для массивов все же дает размер массива, а не указателя:

int n = sizeof(a) / sizeof(*a);

// n=5, т.к. sizeof(a)=20, sizeof(int)=4

int m = sizeof(q) / sizeof(*q);

// m=1, т.к. sizeof(int*)=4, sizeof(int)=4

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]