所以我正在阅读C Primer Plus书,我遇到了关于结构和文件的编程任务。主要目标是为飞机制定座位预订计划。
我定义了以下结构,
typedef struct {
unsigned short identification_number;
unsigned short status;
char last_name[MAX_NAM_LEN];
char first_name[MAX_NAM_LEN];
} Seat;
typedef struct {
unsigned short empty_seats;
Seat seats[]; // Flexible Array Member
} Plane;
我有以下功能打印空座位的识别号码
/*
* Function: print_empty_seats_ID
* -------------------------
* Prints a list of empty seats identification numbers of the given plane.
*
*/
void print_empty_seats_ID (Plane* plane, int num_seats) {
// Clear the screen.
system("clear");
printf("Identification number of empty seats:");
for (int i = 0; i < num_seats; i++) {
if (plane->seats[i].status == EMPTY)
printf(" %d", plane->seats[i].identification_number);
}
puts("");
// Redirect the user to the main menu.
puts("Redirecting in 4 seconds...");
sleep(4);
}
从另一个函数以这种方式调用,print_empty_seats_ID (plane, num_seats);
使得plane
是指向先前在堆上定义的平面结构的指针,而num_seats
是该座位上的总座位数。平面上。
这个函数效果很好,但是如果我把它改为使用值而不是指针调用它会打印垃圾值,如下图所示。
/*
* Function: print_empty_seats_ID
* -------------------------
* Prints a list of empty seats identification numbers of the given plane.
*
*/
void print_empty_seats_ID (Plane plane, int num_seats) {
// Clear the screen.
system("clear");
printf("Identification number of empty seats:");
for (int i = 0; i < num_seats; i++) {
if (plane.seats[i].status == EMPTY)
printf(" %d", plane.seats[i].identification_number);
}
puts("");
// Redirect the user to the main menu.
puts("Redirecting in 4 seconds...");
sleep(4);
}
在这种情况下,函数以这种方式print_empty_seats_ID (*plane, num_seats);
调用,并输出以下废话Identification number of empty seats: 64 0 0
。
我的问题是为什么第一个功能起作用而第二个功能不起作用?
答案 0 :(得分:1)
问题是你正在使用一个所谓的灵活阵列成员,规范说明了这一点:
特别是,结构的大小就像柔性阵列一样 成员被省略,除了它可能有更多的尾随填充 遗漏意味着。
因此,当您按值传递时,座位本身不会被复制。当你通过指针传递它时,指针指向具有座位的原始平面,因此它可以工作..
答案 1 :(得分:1)
问题是您的Plane
有一个灵活的数组成员 seats
,即没有指定大小的尾随数组。这些在C11 6.7.2.1p18:
18 作为一种特殊情况,具有多个命名成员的结构的最后一个元素可能具有不完整的数组类型;这被称为灵活的阵列成员。在大多数情况下,将忽略灵活数组成员。特别是,结构的大小就好像省略了柔性阵列构件一样,除了它可能有比尾部填充更多的尾随填充。
示例6.7.2.1p25澄清了这一点:
25作业:
*s1 = *s2;
[两者都是指向具有灵活数组成员的结构的指针]仅复制[非灵活成员];如果任何数组元素在结构的第一个
sizeof (struct s)
字节内,它们可能被复制或仅仅用不确定的值覆盖。
C中的函数参数通过赋值传递,就像一样,因此适用于按值传递的plane
。