【发布时间】:2016-04-29 14:17:32
【问题描述】:
考虑以下示例程序:
#include <stdio.h>
struct base {
int a, b;
};
struct embedded {
struct base base;
int c, d;
};
struct pointed {
struct base* base;
int c, d;
};
static void base_print(struct base* x) {
printf("a: %d, b: %d\n", x->a, x->b);
}
static void tobase_embedded(void* object) {
base_print(object); // no cast needed, suitably converted into first member.
}
static void tobase_pointed(void* object) {
struct base* x = *(struct base**) object; // need this cast?
base_print(x);
}
int main(void) {
struct embedded em = {{4, 2}};
struct pointed pt = {&em.base};
tobase_embedded(&em);
tobase_pointed(&pt);
return 0;
}
编译:
$ gcc -std=c99 -O2 -Wall -Werror -pedantic -o main main.c
预期的输出是:
$ ./main
a: 4, b: 2
a: 4, b: 2
C99 标准是这样描述结构的第一个成员的:
C99 6.7.2.1 (13): 一个指向结构对象的指针,经过适当的转换,指向它的初始成员......反之亦然。 as 结构对象中可能有未命名的填充,但不是在其开头。
在示例程序中,指向struct embedded 的指针被转换为指向struct base 的指针(通过void*),无需显式转换。
如果第一个成员是struct pointed 中的指向基址的指针怎么办?我不确定tobase_pointed 中的演员阵容。不打印强制转换垃圾,但没有编译警告/错误。通过强制转换,base.a 和 base.b 的正确值会被打印出来,但如果存在未定义的行为,这并不意味着太多。
将struct pointed 转换为其第一个成员struct base* 的演员是否正确?
【问题讨论】:
-
struct pointed的第一个成员是指向struct base的指针。这将需要取消引用void *object。但是你不能在不告诉编译器如何取消引用指针的情况下取消引用void *,因此需要强制转换。
标签: c