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

Указатель – это переменная, которая содержит адрес переменной. Так как указатель – это адрес некоторого объекта, то через него можно обращаться к данному объекту.

В СИ существует тесная связь между указателями и массивами. Любой доступ к элементу массива, осуществляемый операцией индексирования, может быть выполнен при помощи указателя.

Декларация

int a[10];

определяет массив а размера 10, т.е. блок из десяти последовательных объектов, представленных на рисунке, с именами a[0], a[1], …,a[9].

 
 

Запись a[i] отсылает нас к i-му элементу массива. Если ра есть указатель, т.е. определен как

int *pa;, то в результате присваивания

pa = &a[0];

pa будет указывать на нулевой элемент массива а; иначе говоря, ра будет содержать адрес элемента a[0] (см. рис.). Теперь присваивание

x=*pa;

будет копировать содержимое а[0] в х.

Если ра указывает на некоторый элемент массива, то ра+1 по определению указывает на следующий элемент (см. рис.).Таким образом, если ра указывает на a[0], то *(ра+1) есть содержимое a[1], ра+1 – адрес a[1], *(ра+i) – содержимое a[i].

Поскольку имя массива есть не что иное как адрес его начального элемента, присваивание

pa=&a[0];

можно также записать в следующем виде:

pa = a;

Так как ра – указатель, то в выражениях его можно использовать с индексом, то есть запись pa[i] эквивалентна записи *(pa+i). Элемент массива одинаково разрешается изображать и в виде указателя со смещением, и в виде имени массива с индексом.

Между именем массива и указателем, выступающим в роли имени массива, существует одно различие. Указатель – это переменная, поэтому можно написать pa=a или pa++. Но имя массива не является переменной, и запись типа a=pa не допускается.

Следует также различать выражения *(a+2) и *a+2:

*(а+2) – значение третьего элемента массива а;

*а+2 – добавление числа 2 к значению первого элемента массива.

Пример 4. Вывести значения одномерного массива обычным способом и с использованием указателей.

#include <stdio.h>

int a[6]={10,20,30,40,50,60};

/*объявление и инициализация массива*/

main ()

{int i, *p;

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

printf(“%d”,a[i]); /*вывод массива обычным способом*/

for (p=&a[0];p<=&a[5];p++)

printf(“%d”,*p); /*вывод массива с использованием указателя*/

for (p=&a[0],i=0; i<6; i++)

printf(“%d”,p[i]); /*еще один вариант с использованием указателя*/

}

Дадим еще некоторые пояснения. Операция р++ увеличивает значение указателя на единицу. Если p=&a[i], то после операции р++ в р содержится адрес элемента a[i+1].

Пример 5. Найти среднее арифметическое массива, состоящего из шести элементов, с использованием указателя.

#include <stdio.h>

int a[]={10,20,30,40,50,60}

main()

{int i,*p;

float s;

p=a; /*указатель получает значение адреса нулевого элемента массива*/

for (s=0,i=0; i<6; i++)

s+=*(p+i); /*получение суммы элементов массива*/

s=s/6; /*среднее арифметическое массива*/

printf(“%f”,s);

}

Пример 6. Решить задачу, приведенную в примере 1, с использованием указателя.

#include <stdio.h>

main()

{float s[10];

int *p,i;

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

scanf(“%f”,s[i]);

p=&s[9]; /*указатель получает значение адреса последнего элемента массива*/

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

printf(“%f”,*(p-i)); /*вывод элементов в обратном порядке*/

for (p=&a[9]; p>=&a[0]; p--) /*еще один способ вывода элементов в обратном порядке*/

printf(“/n%d”,*p);

}

Предположим, что у нас есть описания:

int z[4][2]; /**/

int pz; / **/

Тогда pz=z указывает на нулевой столбец нулевой строки, т.е.

pz=&z[0][0];

Пример 7. Вывести на экран значения нулевого, второго и четвертого элементов массива.

#include <stdio.h>

int a[]=(10,20,30,40,50,60); /*объявление и инициализация массива а*/

main()

{

for (p=a,i=0; p+i<=a+4; p++, i++)

printf(“%d”; (p+i)); / *вывод на экран значений нулевого, второго и четвертого элементов*/

}

В цикле происходит одновременное увеличение указателя р и индекса i на единицу, вследствие чего на экран после нулевого элемента выводится второй, и затем четвертый. Поскольку элементы двумерного массива хранятся в памяти ЭВМ по строкам, то

pz+1 = &z[0][1], pz+2 = &z[1][0], pz+3 = &z[1][1] и т.д.

Двумерный массив описан как массив массивов. Если z является именем массива, то каковы имена четырех строк, каждая из которых является массивом из двух элементов? Имя первой строки z[0], второй - z[1], и т.д. Однако имя массива является также указателем на этот массив в том смысле, что оно ссылается на первый его элемент. Значит:

z[0]=&z[0][0], z[1]=&z[1][0], z[2]=&z[2][0], z[3]=&z[3][0].

Пример 8. Задана матрица а. Вывести на экран элементы главной диагонали, первой строки и значений первых элементов каждой строки матрицы, применив для этого указатели.

#include <stdio.h>

int a[3][3]={{10,20,30},

{40,50,60},

{70,80,90}};

/*объявление и инициализация двумерного массива*/

int *pa[3]={a[0],a[1],a[2]};

/*объявление и инициализация указателя ра на строки массива а и присвоение начальных значений: pa[0]=a[0]; pa[1]=a[1]; pa[2]=a[2]*/

int p=a[0]; / *объявление указателя на нулевой элемент нулевой строки массива а*/

main ()

{int i;

for (i=0;i<9;i+=4)

printf(“%d”,*(p+i)); /*вывод на экран элементов главной диагонали*/

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

printf(“%d”,*p[i]); /*вывод на экран элементов первой строки*/

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

printf(“%d”,pa[i]); /*вывод на экран первых элементов каждой строки матрицы*/

}

Сделаем некоторые пояснения для первого оператора цикла. Представим матрицу в виде одномерного массива, записанного по строкам:

a[0][0],a[0][1],a[0][2],a[1][0],a[1][1],a[1][2],a[2][0],a[2][1],a[2][2]

Тогда элементы, стоящие на главной диагонали, занимают нулевое, четвертое и восьмое места, т.е. интервал между интересующими нас элементами равен четырем, поэтому переменная i изменяется с шагом 4. Соответственно с таким же шагом меняются адреса ячеек, содержимое которых выводится на экран.

Тема 5: подпрограммы-функцпии


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: