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


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

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



 

Как и для обычных переменных, 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-02-05; просмотров: 322; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.147.104.120 (0.004 с.)