Связь указателей с массивами. Операции обращения по адресу и индексации. Примеры.



Указатели и массивы тесно связаны друг с другом. Имя массива без индекса – это указатель на первый элемент массива. Рассмотрим следующий массив:

charp[10];

Следующие два выражения идентичны:

p &p

Выражение p==&p[0] принимает значение истина, потому что адрес 1-го элемента массива – это то же самое, что и адрес массива.

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

int*p,i[10];

p=i;

p[5]=100; // в присвоении используется индекс

+5)=100; //в присвоении используется адресная арифметика.

Оба оператора присваивания заносят число 100 в 6-ой элемент массива i. Первый из них индексирует указатель p, во втором применяются правила адресной арифметики. В обоих случаях получается один и тот же результат.

Можно также индексировать указатели на многомерные массивы. Например, если а – это указатель на двухмерный массив целых размерностью 10х10, то следующие два выражения эквиваленты:

Тип указателя. Операция преобразования типа указателя. Преобразование типа указателя внутри выражения. Бестиповый указатель. Пустой указатель. Примеры.

Типы

1) Указатель на  void- наа любой тип

2) Указатель на указатель

3) Нулевой указатель- указатель хранящий значение что переменная не ссылается ни на какой объект

Бестиповый указатель- указатель типа void

Массивы указателей. Указатель на указатель. Многомерные массивы и указатели. Примеры.

Можно создавать массивы указателей. Для объявления массива целочисленных указателей из десяти элементов следует написать:

 

int *х[10];

 

Для присвоения адреса целочисленной переменной var третьему элементу массива следует написать:

 

х[2] = &var;

 

Для получения значения var следует написать:

 

*х [2]

 

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

 

void display_array(int *q[])

{

int t;

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

printf ("%d ", *q[t]);

}

 

Надо помнить, что q - это не указатель на целое, а массив указателей на целые. Следовательно, необходимо объявить параметр q как массив целых указателей. Он не может объявиться как простой целочисленный указатель, поскольку он не является им.

 

Типичным использованием массивов указателей является хранение сообщений об ошибках. Можно создать функцию, выводящую сообщение по полученному номеру, как показано ниже:

 

void serror(int num)

{

static char *err[] = {

"Cannot Open File\n",

"Read Error\n",

"Write Error\n",

"Media Failure\n"

};

printf ("%s", err[num]);

}

 

Как можно видеть, printf() в serror() вызывается с указателем на символ, указывающим на одно из сообщений, номер которого передается в функцию. Например, если num приняла значение 2, будет выведено сообщение «Write Error».

Подпрограммы в языке Си (объявление, определение, использование). Формальные и фактические параметры. Передача данных в подпрограмму: неявная, явная (как значения, как адреса (явная, неявная)). Вызов подпрограммы. Стек вызовов. Прототип подпрограммы. Примеры.

Формальный параметр= переменая принимая значение аргумента

Фактический параметр - вызов функции из друих програм. кода

Передача данных в подпрограмме

1) Явно- через параметры

2) Неявно- использование глобальных переменных и временных значений

Прототип- Обозначает, что такая подпрограмма будет определена далоее

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

34. Передача одномерных и многомерных массивов в качестве параметров подпрограмме. Примеры.

При использовании в качестве параметра массива в функцию передается указатель на его первый элемент, иными словами, массив всегда передается по адресу. При этом информация о количестве элементов массива теряется, и следует передавать его размерность через отдельный параметр (в случае массива символов, то есть строки, ее фактическую длину можно определить по положению нуль-символа).

 

Если размерность массива является константой, проблем не возникает, поскольку можно указать ее и при описании формального параметра, и в качестве границы циклов при обработке массива внутри функции.

 

#include <iostream.h>

 

int sum(const int* ma, const int n);

 

int const n = 10;

 

int main(){

 

int marks[n] = {3. 4. 5. 4. 4};

 

cout << "Сумма элементов массива: " << sum(marks, n):

 

return 0;

 

}

 

int sum(const int* mas, const int n)

 

{

 

// варианты: int sum(int mas[], int n)

 

// или int sum(int mas[n], int n)

 

// (величина n должна быть константой)

 

int s = 0;

 

for (int i = 0; i<n; i++)

 

s += mas[i];

 

return s:

 

}

 

При передаче многомерных массивов все размерности, если они не известны на этапе компиляции, должны передаваться в качестве параметров. Внутри функции массив интерпретируется как одномерный, а его индекс пересчитывается в программе. В приведенном ниже примере с помощью функции подсчитывается сумма элементов двух двумерных массивов. Размерность массива b известна на этапе компиляции, под массив а память выделяется динамически:

 

 

 


Дата добавления: 2021-01-21; просмотров: 146; Мы поможем в написании вашей работы!

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






Мы поможем в написании ваших работ!