Передача структуры в качестве аргумента
Для компиляторов, которые разрешают передавать структуры в качестве аргументов, последний пример можно переписать так, как показано в листинге 14.7.
Листинг 14.7. Программа funds3.c

И снова вывод оказывается прежним:
Сумма на счету у Стэна составляет $12576.21.
Мы заменили указатель на struct funds по имени money переменной типа struct funds с именем moolah. При вызове sum() создается автоматическая переменная moolah, согласованная с шаблоном funds. Затем члены этой структуры инициализируются копиями значений соответствующих членов структуры stan. По этой причине вычисления производятся с участием копии исходной структуры, тогда как в предыдущей программе (в которой использовался указатель) задействована сама исходная структура. Так как moolah является структурой, в программе применяется moolah.bankfund, а не moolah->bankfund. С другой стороны, в листинге 14.6 используется money->bankfund, потому что money — указатель, а не структура.
Структуры и другие формы данных 583
Дополнительные возможности структур
Современный язык С позволяет присваивать одну структуру другой — то, чего нельзя делать с массивами. То есть, если n data и o_data — струк туры того же типа, то можно записать следующий код:
o_data = n_data; // присваивание одной структуры другой
Это приводит к тому, что каждому члену n data присваивается значение соответствующего члена o data. Это работает, даже если член оказывается массивом. Кроме того, струк туру можно инициализировать другой структурой того же типа:
struct names right_field = {"Джеймс", "Бонд" };
struct names captain = right_field; //инициализация структуры другой структурой
В современном языке С, включая ANSI С, структуры не только можно передавать функции в качестве аргументов, но также и возвращать их из функции. Применение структур в аргументах функции позволяет передавать ей информацию о структуре. Использование функций для возвращения структур дает возможность передавать информацию о структуре из вызываемой функции в вызывающую. Указатели на структуры также допускают двусторонний обмен данными, так что вы часто будете применять один из этих подходов при решении разнообразных задач. Рассмотрим еще один набор примеров, иллюстрирующих данные два подхода.
Чтобы сравнить эти два подхода, мы напишем простую программу, которая обрабатывает структуры с использованием указателей, и затем переделаем ее лак, чтобы в ней выполнялась передача и возвращение структур. Сама программа запрашивает имя и фамилию и сообщает общее количество букв в них. Этот проект едва ли требует структур, но он предлагает простую инфраструктуру, которая позволяет увидеть, как они работают. В листинге 14.8 представлена версия программы с указателями.
Листинг 14.8. Программа names1.с

584 Глава 14

Компиляция и запуск программы генерирует следующие результаты:
Введите свое имя.
Васисуалий
Введите свою фамилию.
Лоханкин
Васисуалий Лоханкин, ваше имя и фамилия содержат 18 букв.
Работа программы распределена между тремя функциями, вызываемыми в main(). В каждом случае функции передается адрес структуры person.
Функция getinfo() передает информацию изнутри себя в main(). В частности, она получает имена от пользователя и помещает их в структуру person, применяя для доступа к ней указатель pst. Вспомните, что pst->lname означает член lname структуры, на которую указывает pst. Это делает pst->lname эквивалентом имени массива значений char и, следовательно, подходящим аргументом для функции gets(). Обратите внимание, что хотя функция getinfo() снабжает информацией главную программу, она не использует для этого механизм возврата, поэтому имеет тип void.
Функция makeinfo() выполняет двустороннюю передачу информации. С применением указателя на person она находит имя и фамилию, хранящиеся в этой структуре. Она использует функцию strlen() из библиотеки С для подсчета количества букв в имени и фамилии, а затем применяет адрес структуры person для сохранения полученной суммы. Эта функция также имеет тип void. И, наконец, функция showinfo() использует указатель для доступа к информации, предназначенной для вывода. Поскольку showinfo() не изменяет содержимое массива, указатель объявлен как const.
Читать дальше