Consider the following example program:
#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): 指向结构体对象的指针被适当转换后,指向其初始成员...反之亦然。在结构体对象内可能有未命名的填充位,但不能在开头处。
在示例程序中,通过void*将指向struct embedded的指针转换为指向struct base的指针,无需显式转换。
如果第一个成员是指向基类的指针,例如struct pointed中的情况呢?我不确定tobase_pointed中的显式转换是否正确。没有进行转换时会输出垃圾字符,但没有编译警告/错误。进行转换时,将输出base.a和base.b的正确值,但如果存在未定义行为,则意义不大。
将struct pointed转换为其第一个成员struct base*的转换是否正确?
struct pointed
的第一个成员是指向struct base
的指针。这将需要对void *object
进行解引用。但是,您不能在不告诉编译器如何解引用指针的情况下对void *
进行解引用,因此需要进行强制类型转换。 - alvits