Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛекцияУказатели.doc
Скачиваний:
16
Добавлен:
18.04.2015
Размер:
169.98 Кб
Скачать

Указатели и многомерные массивы.

Пример объявления двумерного массива значений типа int: int a[m][n];

Этот массив состоит из m одномерных массивов (строк), в каждом из которых содержится nэлементов (столбцов). При работе с этим двумерным массивом можно использовать 1 или 2 индексных выражения. Например:

a[i][j]- содержит 2 индекса; используется для обращения к элементу i-строки, j-столбца массива; вычисляются индексные выражения, определяется адрес элемента массива и извлекается его значение;

a[i]- содержит 1 индекс; определяет адрес одномерного массива: адрес начала i-строки массива;

а- не содержит индекса и определяет адрес массива, его нулевого элемента.

Таким образом, обращение к двумерным массивам с помощью имени и толь­ко одного индекса определяет указатель на начало соответствующей строки массива (адрес ее нулевого элемента). Например:

а[0] = = &а[0][0] = = а + 0 * n * sizeof(int);

a[l] = = &а[1][0] == a + 1 * n * sizeof(int);

a[i] == &а[i][0] == a + i * n * sizeof(int);

Пример: int mas[4][2];

Двумерный массив можно представить как массив массивов. В нашем случае мы имеем четырех элементный массив, состоящий из двух элементов. Примечательно, что этот четырех элементный массив можно представить в виде одномерного mas[0],…,mas[3]. При этом имя массива по-прежнему является указателем на его первый элемент, т.е. mas[0]= =&mas[0] [0] . На что же будут указывать mas[i]? В этом случае mas [i] указывает на i-тую строку, т.е. на первый элемент i - й строки. Таким образом

mas [0] == &mas [0] [0];

mas [1] == &mas [1] [0];

mas[2] == &mas [2] [0];

mas[3] == &mas [3] [0];

Для доступа к отдельному элементу массива используется конструкция вида a[i][j], гдеiиjвыражения целочисленного типа.

Можно обратиться к элементу массива и другими способами: Выражение a[i][j] компилятор Си++ переводит в эквивалентное выражение *(*(а + i) + j). Разумеется, запись a[i][j] более традиционна в математике и более наглядна.

Обращения к элементу массива *(*(а + i) + j) или *(a[i] + j) приведены для лучшего понимания механизма индексации, по­скольку здесь в явном виде записаны те же действия, которые генерируются ком­пилятором при обычном обращении к массиву. Рассмотрим их подробнее. Допустим, требуется обратиться к элементу, расположенному на пересечении вто­рой строки и третьего столбца — а[2][3]. Как и для одномерных массивов, имя массива а представляет собой константный указатель на начало массива. В данном случае это массив, состоящий из трех массивов. Сначала требуется обратить­ся ко второй строке массива, то есть одномерному массиву а[2]. Для этого надо прибавить к адресу начала массива смещение, равное номеру строки, и выполнить разадресацию: *(а + 2). Напомним, что при сложении указателя с константой учи­тывается длина адресуемого элемента, поэтому на самом деле прибавляется число 2, умноженное на длину элемента, то есть 2 * (5 * sizeof(int)), пocкольку элементом является строка, состоящая из 5 элементов типа int.

Далее требуется обратиться к третьему элементу полученного массива. Для полу­чения его адреса опять применяется сложение указателя с константой 3 (на самом деле прибавляется 3 * sizeof(int)), а затем применяется операция разыменова­ния для получения значения элемента: *(*(а + 2) + 3).

При этом для обращения к массиву а можно использовать имена:

&а = а = &а[0] [0] = *а - адрес а[0] [0]-элемента 0-строки 0-столбца массива.

**а = * (&a[0] [0]) = а [0] [0] - значение элемента 0-строки 0-столбца массива а

a[i]=(а + i) = *(а + i) = &a[i][0] - адрес начала i-строки: адрес элемента i-строки 0-столбца;

*a[i] = **(а + i) = *(&a[i][0]) = a[i][0] - значение 0-элемента i-строки

a[i][j] = *(*(а + i) + j) = *{a[i] + j) = a[i] [j] -значение элемента i-строки j-столбца массива а;

где (a + i) = *(a + i) = a[i] - адрес 0-элемента i-строки = &a[i] [0];

(*(a + i) + j) - адрес j-элемента i-строки = &a[i][j];

*(*(a+i) +j) - значениеj-элементаi-строки =a[i][j].

Значение адреса начала i-строки (адреса 0-элемента i-строки) на машинном уровне формируется в виде:

a[i] =a+i= (а + i * n * sizeof(int)),

где n- количество значений в одной строке.

Пример: Рассмотрим двумерный массив и действия с указателями.

int mas[4][2];

int *ptr;

ptr = mas;

ptr сейчас указывает на первый столбец первой строки, т.е.

ptr = = mas = = &mas [0] [0];

Увеличим указатель:

ptr+1 = = &mas [0] [1];

ptr+2 = = &mas [1] [0];

ptr+3 = = &mas [1] [1] и т.д.

Пример:

#include <stdio.h>

#include <conio.h>

void main()

{ int a[6][5], i, j;

printf("\nRazmer massiva à = %d bait\n", sizeof(a));

for ( i = 0; i < 5; i++)

{ for ( j = 0; j < 6; j++)

{ *(* (a+i)+j) = i + j;

printf(" a[%d][%d] = %d ", i, j, a[i][j]); }

printf("\n"); }

getch();}

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

Razmer massiva р = 120 bait

a[0][0] = 0 a[0][1] = 1 a[0][2] = 2 a[0][3] = 3 a[0][4] = 4 a[0][5] = 5

a[1][0] = 1 a[1][1] = 2 a[1][2] = 3 a[1][3] = 4 a[1][4] = 5 a[1][5] = 6

a[2][0] = 2 a[2][1] = 3 a[2][2] = 4 a[2][3] = 5 a[2][4] = 6 a[2][5] = 7

a[3][0] = 3 a[3][1] = 4 a[3][2] = 5 a[3][3] = 6 a[3][4] = 7 a[3][5] = 8

a[4][0] = 4 a[4][1] = 5 a[4][2] = 6 a[4][3] = 7 a[4][4] = 8 a[4][5] = 9