Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Передача массива




Передача указателя

Передача в функции указателей и массивов

 

В предыдущих примерах в качестве аргументов использовались простые значения типов int или double. Однако часто в качестве аргументов приходится использовать указатели и массивы. Хотя передача в функцию таких аргументов осуществляется так же, как и любых других, однако при их использовании возникают проблемы, которые следует рассмотреть особо.

 

 

Для того, чтобы передать указатель в качестве аргумента, вы должны объявить параметр типа указателя. Вот пример:

// Передача функции указателя.

 

#include <iostream>

using namespace std;

#include <conio>

 

//f() принимает указатель int * в качестве параметра.

void f (int *j); // f() объявляет параметр-указатель

int main () {

int i;

int *p;

 

p = &i; // p теперь указывает на i

f(p); // передача указателя

cout << i; // i теперь равно 100

getch();

return 0;

}

 

// ft) получает указатель на int.

void f (int * j) {

*j = 100; // переменной, на которую указывает j,

// теперь присвоено значение 100

}

 

Рассмотрим внимательно эту программу. Мы видим, что функция f() принимает один параметр: указатель на int. Внутри main() указателю р присваивается значение адреса переменной i. Далее вызывается f() с р в качестве аргумента. Когда параметр-указатель j получает значение р, он так же указывает на i внутри main(). Таким образом, предложение

 

*j = 100;

 

присваивает значение 100 переменной i. В общем случае f() запишет значение 100 по любому адресу, который будет ей передан при вызове.

В предыдущем примере фактически не было необходимости использовать переменную-указатель р. Достаточно при вызове f() указать в качестве аргумента i, предварив это имя значком &. В результате в функцию f() будет передан адрес i. Модифицированная программа имеет такой вид:

 

// Передача функции указателя.

 

#include <iostream>

using namespace std;

#include <conio>

 

void f(int *j);

int main() {

int i;

f (&i); //Нет необходимости в p. В f() непосредственно

// передается адрес i.

cout << i;

getch();return 0;

}

void f(int *j) {

*j = 100; // переменной, на которую указывает j,

// теперь присвоено значение 100

}

 

Существенно, чтобы вы усвоили важное обстоятельство, связанное с передачей в функции указателей: когда вы выполняете внутри функции операцию, использующую указатель, вы фактически работаете с переменной, на которую этот указатель указывает. Это дает возможность функции изменять значение объекта, на который указывает аргумент-указатель.

 

 

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

 

#include <iostream>

using namespace std;

 

void display (int num[10]);

 

int main (){

int t[10], i;

for(i=0; i < 10; ++i) t[i]=i;

display(t); // передача в функцию массива t

return 0;

}

// Выведем несколько чисел.

void display (int num [ 10 ]){

for(int i = 0; i < 10; i++) cout << num[i] << ' ';

}

 

Несмотря на то, что параметр num объявлен как целочисленный массив из 10 элементов, компилятор С++ автоматически преобразует его в указатель на int. Это преобразование необходимо, потому что никакой параметр не может принять целый массив. Поскольку в функцию будет передан указатель на массив, в функции должен быть такой же параметр-указатель для его получения.

Второй способ объявить параметр-указатель состоит в задании параметра в виде массива неопределенной длины, как это показано ниже:

void display (int num [ ]) {

for(int i=0; i < 10; i++) cout << num[i] << ' ';

}

 

Здесь параметр num объявлен как массив неопределенной длины. Поскольку С++ не выполняет проверку на выход за границы массива, фактический размер массива не существенен для параметра (но, разумеется, не для программы). При таком способе объявления компилятор так же автоматически преобразует параметр в указатель на int.

Наконец, num можно объявить как указатель. Этот метод чаше других используется в профессионально написанных программах. Вот пример такого объявления:

void display (int *num) {

for(int i=0; i < 10; i++) cout << num[i] << ' ';

}

 

Возможность объявления параметра как указателя проистекает из того, что любой указатель можно индексировать как массив, используя квадратные скобки [ ]. Заметьте себе, что все три метода объявления массива в качестве параметра дают один и тот же результат: указатель.

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

 

// Измерение содержимого массива с помощью функции.

 

#include <iostream>

using namespace std;

#include <conio>

 

void cube(int *n, int num);

int main() {

int i, nums[10];

for(i=0; i < 10; i++) nums[i]= i+1;

cout << "Исходное содержимое: ";

for(i = 0; i < 10; i ++) cout << nums[i] << ' ';

cout << '\n';

 

cube (nums, 10); // вычисление кубов

cout << "Измененное содержимое: ";

for(i = 0; i<10; i ++) cout << nums[i] << ' ';

getch();

return 0;

}

// Возведение в куб элементов массива.

void cube(int *n, int num){

while (num) {

*n = *n * *n * *n;

num--;

n++;

}

}

 

Ниже приведен вывод этой программы:

 

Исходное содержимое: 1 2 3 4 5 6 7 8 9 10

Измененное содержимое: 1 8 27 64 125 216 343 512 729 1000

 

Мы видим, что после вызова функции cube() массив nums в main() содержит кубы первоначальных значений его элементов. Таким образом, значения элементов nums были модифицированы программными предложениями внутри функции cube(). Это стало возможным потому, что параметр функции n указывает на nums.

 




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


Дата добавления: 2014-01-06; Просмотров: 549; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




Генерация страницы за: 0.008 сек.