将指向结构的指针转换为其第一个成员

Ada*_*dam 8 c

请考虑以下示例程序:

#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;
}
Run Code Online (Sandbox Code Playgroud)

编译:

$ gcc -std=c99 -O2 -Wall -Werror -pedantic -o main main.c
Run Code Online (Sandbox Code Playgroud)

预期的产出是:

$ ./main
a: 4, b: 2
a: 4, b: 2
Run Code Online (Sandbox Code Playgroud)

C99标准说明了结构的第一个成员:

C99 6.7.2.1(13):指向适当转换的结构对象的指针指向其初始成员......反之亦然.在结构对象中可能存在未命名的填充,但在其开头不是.

在示例程序中,指针struct embedded转换为指向struct base(通过void*)的指针,而不需要显式转换.

如果相反第一个成员是指向基数的指针struct pointed怎么办?我不确定内部演员tobase_pointed.没有铸造垃圾被打印,但没有编译警告/错误.随着投了正确的值base.a,并base.b进行打印,但是并没有真正意味着什么,如果有不确定的行为.

演员转换struct pointed成第一个成员struct base*是否正确?

250*_*501 3

该代码不仅进行强制转换,还取消对指向结构基指针的指针的引用。这是首先获得指向基址的指针所必需的。

tobase_pointed如果删除该函数,您的代码中会发生以下情况:

struct pointed pt = {&em.base};
void* object = &pt;                  //pass to the function
struct base** bs = object;           //the cast in the function
assert( bs == (struct base**)&pt ) ; //bs points to the struct pointed
assert( bs == &(pt.base) ) ;         //bs also points to the initial member struct base* base
struct base* b = *bs ;               //the dereference in the function
base_print(x);
Run Code Online (Sandbox Code Playgroud)

bs是经过适当转换以指向初始成员的指针。你的代码是正确的。