В этом разделе рассказывается о передаче структур и их членов функциям.
Передача членов структур функциям
При передаче функции члена структуры передается его значение, притом не играет роли то, что значение берется из члена структуры. Проанализируйте, например, следующую структуру:
struct fred
{
char x;
int y;
float z;
char s[10];
} mike;
Например, обратите внимание, каким образом каждый член этой структуры передается функции:
func(mike.x); /* передается символьное значение x */
func2(mike.y); /* передается целое значение y */
func3(mike.z); /* передается значение с плавающей точкой z */
func4(mike.s); /* передается адрес строки s */
func(mike.s[2]); /* передается символьное значение s[2] */
В каждом из этих случаев функции передается значение определенного элемента, и здесь не имеет значения то, что этот элемент является частью какой-либо большей совокупности.
Если же нужно передать адрес отдельного члена структуры, то перед именем структуры должен находиться оператор &. Например, чтобы передать адреса членов структуры mike, можно написать следующее:
func(&mike.x); /* передается адрес символа x */
func2(&mike.y); /* передается адрес целого y */
func3(&mike.z); /* передается адрес члена z с плавающей точкой */
func4(mike.s); /* передается адрес строки s */
func(&mike.s[2]); /* передается адрес символа в s[2] */
Обратите внимание, что оператор & стоит непосредственно перед именем структуры, а не перед именем отдельного члена. И еще заметьте, что s уже обозначает адрес, поэтому & не требуется.
Передача целых структур функциям
Когда в качестве аргумента функции используется структура, то для передачи целой структуры используется обычный способ вызова по значению. Это, конечно, означает, что любые изменения в содержимом параметра внутри функции не отразятся на той структуре, которая передана в качестве аргумента.
При использовании структуры в качестве аргумента надо помнить, что тип аргумента должен соответствовать типу параметра. Например, в следующей программе и аргумент arg, и параметр parm объявляются с одним и тем же типом структуры.
#include <stdio.h>
/* Определение типа структуры. */
struct struct_type {
int a, b;
char ch;
} ;
void f1(struct struct_type parm);
int main(void)
{
struct struct_type arg;
arg.a = 1000;
f1(arg);
return 0;
}
void f1(struct struct_type parm)
{
printf("%d", parm.a);
}
Как видно из этой программы, при объявлении параметров, являющихся структурами, объявление типа структуры должно быть глобальным, чтобы структурный тип можно было использовать во всей программе. Например, если бы struct_type был бы объявлен внутри main(), то этот тип не был бы виден в f1().
Как уже говорилось, при передаче структуры тип аргумента должен совпадать с типом параметра. Для аргумента и параметра недостаточно просто быть физически похожими; должны совпадать даже имена их типов. Например, следующая версия предыдущей программы неправильная и компилироваться не будет. Дело в том, что имя типа для аргумента, используемого при вызове функции f1(), отличается от имени типа ее параметра.
/* Эта программа неправильная и при компиляции будут
обнаружены ошибки. */
#include <stdio.h>
/* Определение типа структур. */
struct struct_type {
int a, b;
char ch;
} ;
/* Определение структуры, похожей на struct_type,
но сдругими именами. */
struct struct_type2 {
int a, b;
char ch;
} ;
void f1(struct struct_type2 parm);
int main(void)
{
struct struct_type arg;
arg.a = 1000;
f1(arg); /* несовпадение типов */
return 0;
}
void f1(struct struct_type2 parm)
{
printf("%d", parm.a);
}