Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Язык программирования Сpp 25.09.11 (2).doc
Скачиваний:
16
Добавлен:
19.08.2019
Размер:
10.09 Mб
Скачать

Использование указателей в функциях и указатели на функции

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

Рассмотрим задачу умножения двух векторов.

#include <iostream>

#include <windows.h>

using namespace std;

double multVect(int n,double x[],double y[]){/*скалярное произведение*/

double z=0;

for(int i=0;i<n;i++) z=z+x[i]*y[i];

return z;

}

void main(){

SetConsoleOutputCP(1251);

double u[]={1.0, 2.0, 3.0}, v[]={4.0, 5.0, 6.0};

cout<<”Произведение векторов=”<<multVect(3,u,v);

}

Иногда возвращаемое значение функции должно быть указателем. Рассмотрим программу на примере объединения массивов.

#include <iostream>

#include <windows.h>

using namespace std;

//объявляем и описываем фунцию

double *connectVect(int n, double* x, int m, double* y){ int i;

double *z=new double[n+m]; //выделяем память

for(i=0;i<n;i++) z[i]=x[i]; //заносим в память

for(i=n;i<n+m;i++) z[i]=y[i-n];

return z;

}

void main(){

SetConsoleOutputCP(1251);

double u[]={1.0, 2.0, 3.0}, v[]={4.0, 5.0, 6.0, 7.0, 8.0}, *w;

w=connectVect(3,u,5,v);

cout<<"Объединение массивов"<<endl;

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

cout<<w[i]<<endl;

}

Любая функция представляет собой код с определенным именем. Для размещения функции компилятор языка С++ находит в памяти подходящий объем свободных ячеек с непрерывными адресами и записывает этот код в память последовательно занимая её свободные ячейки. Указателем на начало кода является имя функции, а его значением служит адрес первой ячейки, занимаемый кодом функции. Тип указателя определяется типом возвращаемого значения. Раз так, то возникает вопрос: нельзя ли вызвать функцию используя указатель? Ответ очень простой: можно. Для этого адрес начала кода функции должен быть присвоен новому указателю, который можно использовать для вызова функции. Конечно этот новый указатель должен иметь тот же тип, что и возвращаемое значение функции. Более того, сигнатура нового указателя должна быть такой же как у функции. Ведь функция в общем случае потребует передачи значений своих параметров. Иными словами синтаксис объявления указателя на функцию должен быть таким

тип_функции (*имя_указателя)(список_спецификаций_параметров);

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

int (*multiplay)(int, int);

Обратите внимание, что имя указателя записывается в круглых скобках, в противном случае компилятор поймет его как прототип функции multiplay, которая возвращает значение указателя типа int.

В качестве примера вновь запишем программу для произведения векторов.

#include <iostream>

#include <windows.h>

using namespace std;

double multVect(int n,double x[],double y[]){/*объявление функции*/

double z=0;

for(int i=0;i<n;i++) z=z+x[i]*y[i];

return z;

}

//--------------------------------------

void main(){

SetConsoleOutputCP(1251);

double u[]={1.0, 2.0, 3.0}, v[]={4.0, 5.0, 6.0};

double (*ptrFun)(int, double[], double[]); /*объявление указателя с именем ptrFun */

ptrFun=multVect; /*в новый указатель записывается адрес функции */

cout<<"Произведение векторов="<<ptrFun(3,u,v)<<endl;

cout<<"Произведение векторов="<<(ptrFun)(3,u,v)<<endl; /* При вызове функции через указатель его имя можно взять в скобки */

}

Функция main()

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

Стандарт функции main() допуcкает два формата – без параметров,

тип main(){/*тело функции*/}

и с двумя параметрами

тип main(int argc, char* argv[]){/*тело функции*/}

Имена параметров в программе могут быть любыми, но общепринятыми являются argc и argv.

Первый параметр argc определяет количество аргументов, второй argv является указателем на массив указателей типа char.Каждый элемент массива это указатель на отдельный параметр командной строки, хранящейся в виде С-строки, оканчивающейся нуль-символом. Первый элемент массива argv[0] ссылается на полное имя запускаемого на выполнение файла, и поэтому количество элементов массива не может быть меньше 1. Следующий argv[1] указывает на первый параметр, argv[2] указывает на второй параметр и т.д. Параметр argv[argс] должен быть равен нулю.

Если функция main() выполнилась до конца, то вызвавшая ее система получит значение 0, означающее успешное завершение. Ненулевое значение означает аварийное завершение. Оператор возврата return из main() можно опускать. Вот простой пример, иллюстрирующий сказанное.

Наберите следующую программу.

#include<iostream.h>

#include<windows.h>

//#include<string.h>

int main(int argc,char* argv[]){

SetConsoleOutputCP(1251);

SetConsoleCP(1251);

if(argc!=2){

cout<<"Вы забыли указать свое имя.\n";

exit(1);

}

cout<<"Привет!"<<argv[1];

return 0;

}

Откомпилируйте и сохраните ее под каким-нибудь именем. Если вы используете Builder, то для сохранения воспользуйтесь File/save All. Далее воспользуйтесь каким-нибудь файловым менеджером, например, Windows Commander, Far или Volkov Commander. Найдите свой файл. Пусть его имя будет Project2.exe, и запустите его. Если после запускаемого файла указать свое имя, то программа выведет приветствие