Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Тема 6,7,8 базовый Си.docx
Скачиваний:
4
Добавлен:
16.11.2018
Размер:
117.96 Кб
Скачать

8.3 Особые случаи передачи аргументов

8.3.1 Передача аргументом одномерного массива

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

  1. Формальный аргумент, объявленный как массив переменных соответствующего типа, пределов для которого опущено . В теле функции для работы с элементами такого массива використують переменные с индексом .

  2. Пример 6: сумма елеметiв массива (вариант 1).

  3. Void summa1 (Float X [] , int n, float * s)

  4. {Float res = 0.0;

  5. int i;

  6. for (i = 0; i <n; i + +)

  7. res + = x [i] ;

  8. * S = res;

  9. }

  10. Формальный аргумент, объявленный как указатель на переменную соответствующего типа . В теле функции для работы с элементами такого массива використуютьуказатели i адресную арифметику .

  11. Пример 7: сумма елеметiв массива (вариант 2).

  12. Void summa2 (float * x , int n, float * s)

  13. {Float res = 0.0;

  14. int i;

  15. for (i = 0; i <n; i + +)

  16. res + = * (x + i) ;

  17. * S = res;

  18. }

8.3.2 Передача аргументом многомерного массива

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

Пример 8:

main ()

{Double xyz [10] [15] [7];

f (double [] [15] [7]);

...

f (xyz);

}

f (double a [] [15] [7]) / * пропущено Первая граница * /

{...}

Для двумерного массива обязательно объявить количество столбцов, количество строк сообщать необязательно.

Пример 9: передача аргументом массива праздничных дней.

f1 (INT MPR [2] [7] ) {...}

f2 (INT MPR [] [7] ) {...}

f3 (int (* pmpr) [7]) {...}

! В функции скобки необхднi через приоритет операций: proi []> prio *.

8.3.3 Передача аргументом структуры

Над структурами допустимы такие "операции":

  1. копирование;

  2. присваивания;

  3. взятие адреса;

  4. доступ к ее членов;

  5. инициализация.

! Невозможно структуры сравнивать.

Копированию соответствует передача структуры аргументом в функции .

Присваиванию отвечает возвращения структуры как результата функции .

Существует три подхода к передаче структур в функцию и возврат из нее:

  1. передача ее членов в отдельности;

  2. передача структуры вполне;

  3. передача указателя на структуру.

Пример 10: объекты, для которых будем выполнять операции со структурами.

объекты типа

__________________________________________________________________

"Точка" | "прямоугольник"

__________________|_______________________________________________

Struct Point | Struct Rect

{Int x; | {struct point pt1; / * левый верхний угол * /

int y; | struct point pt2; / * правый нижний угол * /

}; |};

__________________|_______________________________________________

С помощью объектов этих типов напишем несколько функций.

Пример 11: формирование точки по ее компонентам.

struct point makepoint (int x, int y)

{Struct point temp;

temp.x = x;

temp.y = y;

return temp;

}

Определим с помощью этой функции объект "экран" (как прямоугольник размером с экран монитор).

объект "середина экрана" (как точку с координатами центра экрана).

Пример 12: формирование объектов "экран" i "середина экрана".

# Define MAXX 639

# Define MAXY 349

# Define MINX 0

# Define MINY 0

...

struct rect screen; / * объект "экран" * /

struct point middle; / * объект "середина экрана" * /

struct point makepoint (int, int);

/ * Создание левого верхнего угла объекта "экран": * /

screen.pt1 = makepoint (MINX, MINY);

/ * Создание правого нижнего угла объекта "экран": * /

screen.pt2 = makepoint (MAXX, MAXY);

/ * Создание объекта "середина экрана: * /

middle = makepoint ((screen.pt1.x + screen.pt2.x) / 2,

(Screen.pt1.y + screen.pt2.y) / 2

);

Пример 13: добавление точек.

Struct Point addp (struct point p1, struct point p2)

{P1.x + = p2.x;

p1.x + = p2.x;

return p1;

}

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

Пример 14: принадлежит ли точка p прямоугольнике r?

pt_in_rect (struct point p, struct rect r)

{Return

px> = r.pt1.x & & px <= r.pt2.x & &

py> = r.pt1.y & & py <= r.pt2.y;

} / * Результат не является 0, если точка p принадлежит прямоугольнику r ,

иначе результат есть 0 * /

Указатели на структуры ничем не отличаются от указателей на обычные переменные.

Пример 15: указатели на структуры

struct point * ps; / * указатель на структуру * /

struct point t;

struct point makepoint (int, int);

t = struct point makepoint (15, 25);

ps = &t;

/ * * Ps - это структура t

(* Ps). X = 15

(* Ps). Y = 25 * /

printf ("Это t: (% d,% d)", (* ps). x, (* ps). y);

Скобки в этом примере нужны потому, что prio (.)> prio (*).

Оператор ->:

Синтаксис:

<Указатель на структуру> -> <имя члена структуры>

Семантика:

Если р - указатель на структуру , то г -> <член структуры> - это ее член.

Свойства оператора -> :

  • бинарный;

  • iнфиксний;

  • наивысший приоритет;

  • лiвоасоцiативний.

Пример 16: эквивалент примера 15.

...

printf ("Это t: (% d,% d)", ps -> x, ps-> y);

Пример 17:

struct rect r, * pr;

pr = &r;

/ * Эквивалентные: * /

1) r.pt1.x

2) pr-> pt1.x

3) (r.pt1). X

4) (pr-> pt1). X

Пример 18: передача структуры аргументом по ссылке.

main ()

{Struct point p;

struct point makepoint (int, int);

void put (struct point *);

p = makepoint (10, 12);

put (& p);

}

void put (struct point *)

{Print ("x =% d, y =% d", p -> x, p -> y);

/ * Или print ("x =% d, y =% d", (* p). X, (* p). Y) * /

}

Пример 19: Использование нескольких операторов для работы

со структурами с учетом приоритета операторов.

struct

{Int len; / * длина строки * /

char str; / * строка * /

} * P;

+ + P-> len; / * len + +, а не p + + * /

+ + (P-> len); / * эквивалентна * /

(+ + P) -> len; / * 1) + + p; (перейти к следующей строке) * /

/ * 2). Len; (взять его длину) * /

(P ++)-> len; / * 1). Len; (взять длину строки) * /

/ * 2) p + +; (перейти к следующей строке) * /

p + + -> len; / * эквивалентна * /

* P-> str; / * * p-> str (то, на что ссылается str - str [0] ) * /

* (P-> str); / * эквивалентна * /

* P-> str + +; / * 1) * p-> str (то, на что ссылается str - str [0] ) * /

/ * 2) str + +;

/ * (Перейти к следующему элементу - str [1] ) * /

(* P-> str) + +; / * 1) * p-> str (то, на что ссылается str - str [0] ) * /

/ * 2) увеличение на 1 кода символа, который содержится в str [0] ) * /

* P + + -> str; / * 1) * p-> str (то, на что ссылается str - str [0] ) * /

/ * 2) p + +; (перейти к следующей строке) * /