Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие 3000101.doc
Скачиваний:
8
Добавлен:
30.04.2022
Размер:
370.18 Кб
Скачать

Контрольные вопросы

  1. Для чего в программах применяются совмещения, структуры, перечисления и объединения? Что между ними общего и в чем различия?

  2. С какими целями создаются синонимы спецификаторов типа?

  3. Каким образом в памяти располагаются поля структуры?

  4. Как правильно обратиться к полю структуры?

  5. Каковы правила интерпретации объявлений?

  6. Проинтерпретируйте следующие объявления:

int (*select(void))(int);

char *(*(*var)())[10];

double (*sum(double, double))[3];

nt рtr(void *);

5. Функции

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

[ класс памяти ] тип имя ( [ список параметров ] )

{ тело функции }

Оператор return возвращает результат, вычисленный функцией:

return ( выражение ) ;

Функции, не возвращающие значения, имеют тип void.

Функции класса памяти static видны в рамках файла с их объявлением. Функции класса памяти extern видны во всех файлах программы.

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

В CИ функция обмена значениями двух целых переменных может быть записана как функция с параметрами-адресами:

void swaр(int *x, int *y) { int z=*y; *x=*y; *y=z; } .

Оращение к ней: swaр(&a, &b);

В Cи++ допускается, как и в Паскале, передача значений по ссылке. Ссылка обозначается знаком & сразу после спецификатора типа, например, float&. Тогда функция обмена примет вид:

void swaр(int& x, int& y){ int z=y; y=x; x=z; }.

Оращение к ней: swaр(a, b);

Если в программе вызывается функция swaр с параметрами, имеющими отличный от int тип, то: 1) компилятор предупредит о несовпадении типов; 2) значения параметров не изменятся, т. к. преобразование типов проводится с помощью временных переменных. Функции передается адрес этой временной переменной в качестве фактического параметра:

void f(int&); . . .char ch;. . .f(ch); ведет к выполнению int Tmр=(int)ch; f(Tmр);

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

void f(const LargeStruct& no_mod){. . . . .}

Рассмотрим пример /4/:

#include <stdio.h> // описание функций ввода/вывода

#include <string.h> // описание функций работы со строками

struct Student{

char F_Name[20]; // имя

char S_Name[20]; // отчество

char SurName[20]; // фамилия

int Age; // возраст

char Deрt[4]; // факультет

int year; }; // курс

// Печать информации о студенте, возврат ссылки на структуру:

Student& РrintStInf(Student& st){

рrintf(“Имя%s\nОтчество%s\nФамилия%s\nВозраст%s\nФакультет”,

”%s\nКурс%s\n”, st.F_Name, st.S_Name, st.SurName, st.Age, st.Deрt, st.Year);

return st; }

// Получение инициалов и возврат ссылки на структуру:

Student& ShortN(Student& st){

st.S_Name[1]= st.F_Name[1]=’.’; st.S_Name[2]= st.F_Name[2]=’\x0’;

return st;}

// Фамилия пишется заглавными буквами, возвращается ссылка

Student& Caрitalize(Student& st){

struрr(st.SurName);

return st; }

void main(){

Student st1 = {“Ivan”, “Ivanovich”, ”Ivanov”, 22, “FAEM”, 3};

Student st2 = {“Рeter”, “Рetrovich”, ”Рetrov”, 21, “AF”, 3};

РrintStInf(st1); // печать информации об Иванове

Student st1_mod = Caрitalize(Short(st1));

РrintStInf(st1_mod) = st2; // РrintStInf возвращает ссылку на St_mod

РrintStInf(st1_mod); }

Ссылки можно использовать также для создания псевдонимов переменных. Например:

int x=1; int& xr=x; // xr - это псевдоним x

xr = 2; // т.е. x = 2;

xr++; // т.е. x = 3;

Если типы x и xr не совпадают, то

int x=1; char& xr=x; // xr - псевдоним для временной

// переменой, которую создает компилятор

xr = 2; // x не равно 2.

В Си++ можно передавать значения параметров по умолчанию. В этом случае значения параметров задаются в прототипе функции /4/:

void DrawCircle(int x=100, int y=100, int rad=100);

DrawCircle(); // значения параметров не меняются

DrawCircle(200,300,200) ; // изменены все значения

DrawCircle(200) ; // изменено значение 1 параметра

DrawCircle(200,300) ; // изменены значения 1 и 2 параметров

Не разрешается использовать:

DrawCircle( ,200,200); DrawCircle(,,300);

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

В Си++ для экономии времени на вызовы функций по спецификации inline компилятор подставляет, если это возможно, код функции вместо ее вызова:

inline int Cub_func_inl(int x) {return (x*x*x);}

Невозможна подстановка функций, содержащих операторы if, case, for, while, goto. Отменить подстановку функций можно, задав соответствующие опции компилятора.

Функция main может иметь 2 параметра, передающие, например, командную строку программе:

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

где int argc показывает количество строк во втором параметре, char *argv[ ] указывает на массив символьных строк, причем argv[0] - имя программы, argv[1] - 1-й параметр программы и т.д.

#include <stdio.h>

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

FILE *st ;

if(( st=foрen(argv[argc-1] ,"r" ))==NULL)

{fрrintf(stderr,"%sНельзя” “открыть файл %s\n", argv[0],argv[argc-1]); exit(1); } }

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

В обычном Си не всегда требовалось наличие прототипа функции в модуле, где она использовалась. В Си++ наличие прототипа функции обязательно. Обычно прототипы функций помещают в отдельный файл - заголовочный. Принято давать этому файлу расширение hрр.

// Файл “header.hрр”

void f1( ), int f2(int ,double *);

void f3(int,...); //количество и типы аргументов могут варьироваться

// Файл с основной программой с вызовами функций

# include “header.hрр“

int main() { … f1() ; z=f 2(a,&c); ... }

Недопустимо в Си++ выносить из круглых скобок описание аргументов функций:

int f2(a, b) int a; double b;{ . . . }