- •Тема 6. Структуры
- •6.1 Понятие структуры в языке Си
- •6.2 Объявление типа структуры
- •6.3 Декларация переменных структурного типа
- •6.4 Доступ к элементам структурной переменной
- •6.5 Массивы структур
- •6.6 Оператор sizeof
- •6.7 Декларация typedef
- •7.2 Определение функции
- •7.3 Функции, вызывающие, I функции, вызываемые
- •7.4 Связи по данным между функциями
- •7.4.1 Вызов функции
- •7.4.2 Инструкция return (возврат)
- •7.5 Аппарат формальных и фактических аргументов
- •Входные аргументы;
- •Выходные аргументы;
- •Аргументы, которые обновляются.
- •7.6 Прототип функции
- •Тема 8. Передача аргументов функций
- •8.1 Способы передачи аргументов
- •8.1.1 Передача аргументов по значению
- •8.1.2 Передача аргументов по имени
- •8.1.3 Передача аргументов по ссылке
- •8.2 Особенности передачи аргументов в языке Си
- •8.3 Особые случаи передачи аргументов
- •8.3.1 Передача аргументом одномерного массива
- •Пример 6: сумма елеметiв массива (вариант 1).
- •Пример 7: сумма елеметiв массива (вариант 2).
- •8.3.2 Передача аргументом многомерного массива
- •8.3.3 Передача аргументом структуры
- •8.4 Аргументы командной строки
8.3 Особые случаи передачи аргументов
8.3.1 Передача аргументом одномерного массива
Возможны два способа объявления формального аргумента:
-
Формальный аргумент, объявленный как массив переменных соответствующего типа, пределов для которого опущено . В теле функции для работы с элементами такого массива використують переменные с индексом .
-
Пример 6: сумма елеметiв массива (вариант 1).
-
Void summa1 (Float X [] , int n, float * s)
-
{Float res = 0.0;
-
int i;
-
for (i = 0; i <n; i + +)
-
res + = x [i] ;
-
* S = res;
-
}
-
Формальный аргумент, объявленный как указатель на переменную соответствующего типа . В теле функции для работы с элементами такого массива використуютьуказатели i адресную арифметику .
-
Пример 7: сумма елеметiв массива (вариант 2).
-
Void summa2 (float * x , int n, float * s)
-
{Float res = 0.0;
-
int i;
-
for (i = 0; i <n; i + +)
-
res + = * (x + i) ;
-
* S = res;
-
}
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 Передача аргументом структуры
Над структурами допустимы такие "операции":
-
копирование;
-
присваивания;
-
взятие адреса;
-
доступ к ее членов;
-
инициализация.
! Невозможно структуры сравнивать.
Копированию соответствует передача структуры аргументом в функции .
Присваиванию отвечает возвращения структуры как результата функции .
Существует три подхода к передаче структур в функцию и возврат из нее:
-
передача ее членов в отдельности;
-
передача структуры вполне;
-
передача указателя на структуру.
Пример 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;
}
Определим с помощью этой функции объект "экран" (как прямоугольник размером с экран монитор).
i объект "середина экрана" (как точку с координатами центра экрана).
Пример 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 + +; (перейти к следующей строке) * /