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

 

Как и для обычных переменных, C++ поддерживаeт как вызов функции с передачей копии всей структурной переменной или только отдельных ее полей (Call-By-Value), так и с передачей указателя на всю структурную переменную или только на отдельные поля структурной переменной (Call-By-Reference). Функция может возвращать как структурную переменную, так и указатель на нее.

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

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

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

Первая функция, makepoint, получает два целых значения и возвращает структуру point.

// makepoint: формирует точку по компонентам х и у

struct point makepoint( int x, int y)

{

struct point temp;

temp.x = x;

temp.y = y;

return temp;

}

Заметим: никакой путаницы из-за того, что имя аргумента совпадает с именем члена структуры не возникает; более того, одно и то же имя подчеркивает родство обозначаемых им объектов.

Теперь с помощью makepoint можно выполнять динамическую инициализацию любой структуры или формировать структурные аргументы для той или иной функции:

struct rect screen;

struct point middle;

struct point makepoint( int, int);

screen.pt1 = makepoint(0, 0);

screen.pt2 = makepoint(XMAX, YMAX);

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

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

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

// addpoint: сложение двух точек

struct point addpoint(struct point p1, struct point p2)

{

p1.x += p2.x;

p1.y += p2.y;

return p1;

}

Здесь оба аргумента и возвращаемое значение – структуры. Мы увеличиваем компоненты прямо в р1 и не используем для этого временной переменной, чтобы подчеркнуть, что структурные параметры передаются по значению так же, как и любые другие.

В качестве другого примера приведем функцию ptinrect, которая проверяет: находится ли точка внутри прямоугольника, относительно которого мы принимаем соглашение, что в него входят его левая и нижняя стороны, но не входят верхняя и правая.

// printrect: возвращает 1, если р в r, и 0 в прот. случае

int ptinrect(struct point p, struct rect r)

{

return p.x >= r.pt1.x && p.x < r.pt2.x && p.y >= r.pt1.y && p.y < r.pt2.y;

}

Здесь предполагается, что прямоугольник представлен в стандартном виде, т.е. координаты точки pt1 меньше соответствующих координат точки pt2. Следующая функция гарантирует получение прямоугольника в каноническом виде.

#define min(a, b) ((a)<(b)?(a):(b))

#define max(a, b) ((a)>(b)?(a):(b))

// canonrect: канонизация координат прямоугольника

struct rect canonrect(struct rect r)

{

struct rect temp;

temp.pt1.x = min(r.pt1.x, r.pt2.x);

temp.pt1.y = min(r.pt1.y, r.pt2.y);

temp.pt2.x = max(r.pt1.x, r.pt2.x);

temp.pt2.y = max(r.pt1.y, r.pt2.y);

return temp;

}

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

Декларация

struct point *pp;

сообщает, что рр есть указатель на структуру типа struct point. Если рр ссылается на структуру point, то *рр есть сама структура, а (*рр).х и (*рр).у – ее члены. Используя указатель рр, мы могли бы написать

sctruct point origin, *pp;

pp = &origin;

printf("origin: (%d, %d)\n", (*pp).x, (*pp).y);

Скобки в (*рр).х необходимы, поскольку приоритет оператора . выше, чем приоритет *. Выражение *рр.х будет проинтерпретировано как *(рр.х), что неверно, поскольку рр.х не является указателем.

 








Дата добавления: 2017-01-29; просмотров: 759;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

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

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.006 сек.