Функции, массивы и указатели.

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

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

 

/* массив-аргумент */ main () { int ages [50]; /* массив из 50 элементов */ convert(ages); … }   convert (years) int years []; /* каков размер массива? */ { … }  

 

 

Очевидно, что массив ages состоит из 50 элементов. А что можно сказать о массиве years? Оказывается, в программе нет такого массива. Описатель int years[]; создает не массив, а указатель на него.

Вот вызов нашей функции:

convert(ages);  

 

ages — аргумент функции convert. Вы помните, что имя ages является указателем на первый элемент массива, состоящего из 50 элементов. Таким образом, оператор вызова функции передает ей указатель, т. е. адрес функции convert (). Это значит, что аргумент функции является указателем, и мы можем написать функцию convert () следующим образом:

convert (уears) int *years; { }  

 

 

Действительно, операторы

 

int years [];

int * years ;

 

синонимы. Оба они объявляют переменную years указателем массива целых чисел. Однако главное их отличие состоит в том, что первый из них напоминает нам, что указатель years ссылается на массив.

Использование указателей при работе с массивами.

Попробуем написать функцию, использующую массивы, а затем перепишем ее, применяя указатели.

Рассмотрим простую функцию, которая находит (или пытается найти) среднее значение массива целых чисел. На входе функции мы имеем имя массива и количество элементов. На выходе получаем среднее значение, которое передается при помощи оператора return. Оператор вызова функции может выглядеть следующим образом:

 

/* X54.C */ #include <stdio.h> void main(void) { int n1=9,i, *pa1,*pa,n; int array[] = {9,5,3,1,0,-9,-5,-3,-1}; pa1=array; int mean(int *pa,int n); i = mean(pa1,n1); printf("Average is %d\n",i); } int mean(int *pa,int n)   { int index; long sum; if(n > 0) { for(index = 0, sum = 0; index < n; index++) sum += *(pa+index); return((int) (sum/n)); } else { printf("Net massiva\n"); return(0); } }  

 

 

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

 

 

Эту программу легко переделать, применяя указатели. Объявим ра указателем на тип int. Затем заменим элемент массива array[index] на соответствующее значение: *(ра + index).

 

/* Использование указателей для нахождения среднего значения массива n целых чисел */ int mean(pa, n) int *pa, n; { int index; long sum; /*Если целых слишком много, их можно суммировать в формате long int */ if (n > 0) { for (index = 0, sum = 0; index < n: index++) sum += *(pa + index); return((int) (sum/n) ); /* Возвращает целое */ } else { printf(" Нет массива. \n"); return(0); } }  

 

Строки (массивы типа char).

// 10CHRARY.CPP // Программа на C++, печатающая массив символов в обратном порядке // и использующая указатель на символ и оператор декремента   #include "stdafx.h" #include "E:\LECTURE\AlgorithmProgramming 02\Universal_HederFile.h"   void StopWait(void);   void main() { char pszpalindrome[]="POOR DAN IN A DROOP"; char *pc; pc=&pszpalindrome[0]+(strlen(pszpalindrome)-1); do { cout << *pc; pc--; } while (pc >= pszpalindrome); cout << endl;   StopWait(); /* Wait a little */ }    

Многие строковые операции в С обычно выполняются с использованием указателей и арифметических операций с указателями для доступа к элементам символьного массива. Это обусловлено тем, что символьные массивы или строки, как правило, обрабатываются строго последовательно. Напоминаем, что все строки в С заканчиваются символом null (\0). Следующая программа на C++ иллюстрирует использование указателей с символьными массивами:

 

 

ПРИМЕЧАНИЕ.

Функция strlen() считает только символы. Она не включает в результат null - символ \0

 

77. Указатели. Массивы указателей. Дополнительная информация об указателях на указатели. Массивы указателей на строки.

 

Указатель — переменная, содержащая адрес объекта. Указатель не несет информации о содержимом объекта, а содержит сведения о том, где размещен объект.

Память компьютера можно представить в виде последовательности пронумерованных однобайтовых ячеек, с которыми можно работать по отдельности или блоками.

Каждая переменная в памяти имеет свой адрес - номер первой ячейки, где она расположена, а также свое значение. Указатель — это тоже переменная, которая размещается в памяти. Она тоже имеет адрес, а ее значение является адресом некоторой другой переменной. Переменная, объявленная как указатель, занимает 4 байта в оперативной памяти (в случае 32-битной версии компилятора).

Указатель, как и любая переменная, должен быть объявлен.
Общая форма объявления указателя

 

тип *ИмяОбъекта;

 

Тип указателя— это тип переменной, адрес которой он содержит.

Для работы с указателями в Си определены две операции:

операция * (звездочка) — позволяет получить значение объекта по его адресу - определяет значение переменной, которое содержится по адресу, содержащемуся в указателе;

операция & (амперсанд) — позволяет определить адрес переменной.

Например,

сhar c; // переменная char *p; // указатель p = &c; // p = адрес c