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



 

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

 

Вызов функций с указателями

 

В C++ разрешается передавать функции указатели. Для этого достаточно объявить параметр типа указатель. Рассмотрим пример.

 

 

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

 

 

переменная i получает значение 100 . Поэтому программа отобразит на экране число 100 . В общем случае приведенная здесь функция f() присваивает число 100 переменной, адрес которой был передан этой функции в качестве аргумента.

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

 

 

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

 

Вызов функций с массивами

 

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

 

 

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

Второй способ объявления параметра‑массива состоит в его представлении в виде безразмерного массива, как показано ниже.

 

 

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

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

 

 

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

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

 

 

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

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

 

 

Результаты выполнения этой программы таковы.

 

 

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

 

Передача функциям строк

 

Как вы уже знаете, строки в C++ – это обычные символьные массивы, которые завершаются нулевым символом. Таким образом, при передаче функции строки реально передается только указатель (типа char*) на начало этой строки. Рассмотрим, например, следующую программу. В ней определяется функция stringupper() , которая преобразует строку символов в ее прописной эквивалент.

 

 

Результаты выполнения этой программы таковы.

 

 

Обратите внимание на то, что параметр str функции stringupper() объявляется с использованием типа char* . Это позволяет получить указатель на символьный массив, который содержит строку. Рассмотрим еще один пример передачи строки функции. Как вы узнали в главе 5, стандартная библиотечная функция strlen() возвращает длину строки. В следующей программе показан один из возможных вариантов реализации этой функции.

 

 

Вот как выглядят результаты выполнения этой программы.

 

 

В качестве упражнения вам стоило бы попытаться самостоятельно реализовать другие строковые функции, например strcpy() или strcat() . Этот тест позволит узнать, насколько хорошо вы освоили такие элементы языка C++, как массивы, строки и указатели.

 


Дата добавления: 2018-09-22; просмотров: 301; Мы поможем в написании вашей работы!

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






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