为什么在创建结构时需要地址运算符(&)?

Why is address operator (&) needed when creating struct?

我有一些代码可以工作,但我不明白为什么。这是有问题的代码:

struct SceneInterface *TitleAsScene = &(struct SceneInterface) {
    .update = (void (*)(void *)) title_update,
    .render = (void (*)(void *)) title_render,
};

我得到了函数指针和指定的初始化程序,但是 &(struct SceneInterface) 部分在做什么?一般是address of,但是括号里的东西是类型,不是变量,那它指的是什么呢?如果它返回一个指向 struct SceneInterface 的指针,那么左侧已经是那个,所以我不明白为什么需要它以及为什么如果删除它会出现分段错误。

这里是完整的工作代码供参考:

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

struct SceneInterface {
    void (*update)(void *instance);
    void (*render)(void *instance);
};

struct Scene {
    void *instance;
    const struct SceneInterface *interface;
};

struct Scene *scene_create(void *instance, struct SceneInterface *interface)
{
    struct Scene *scene = (struct Scene *) malloc(sizeof(struct Scene));
    scene->instance = instance;
    scene->interface = interface;

    return scene;
}

void scene_update(struct Scene *scene)
{
    // return this if function has a return type
    (scene->interface->update)(scene->instance);
}

void scene_render(struct Scene *scene)
{
    (scene->interface->render)(scene->instance);
}

struct Boot {
    double x;
};

struct Boot *boot_create(double sideLength)
{
    struct Boot *boot = (struct Boot *) malloc(sizeof(struct Boot));
    boot->x = sideLength;

    return boot;
}

void boot_update(struct Boot *boot)
{
    printf("boot update\n");
}

void boot_render(struct Boot *boot)
{
    printf("boot render\n");
}

struct Title {
    double radius;
};

struct Title *title_create(double radius)
{
    struct Title *title = (struct Title *) malloc(sizeof(struct Title));
    title->radius = radius;

    return title;
}

void title_update(struct Title *title)
{
    printf("title update\n");
}

void title_render(struct Title *title)
{
    printf("title render\n");
}

int main(int argc, char **argv)
{
    struct Boot *boot = boot_create(10.0);
    struct Title *title = title_create(5.0);

    struct SceneInterface *BootAsScene = &(struct SceneInterface) {
        .update = (void (*)(void *)) boot_update,
        .render = (void (*)(void *)) boot_render,
    };
    struct SceneInterface *TitleAsScene = &(struct SceneInterface) {
        .update = (void (*)(void *)) title_update,
        .render = (void (*)(void *)) title_render,
    };

    struct Scene *bootScene = scene_create(boot, BootAsScene);
    struct Scene *titleScene = scene_create(title, TitleAsScene);

    boot_update(boot);
    scene_update(bootScene);

    boot_render(boot);
    scene_render(bootScene);

    title_update(title);
    scene_update(titleScene);

    title_render(title);
    scene_render(titleScene);

    return 0;
}
    struct SceneInterface *BootAsScene = &(struct SceneInterface) {
        .update = (void (*)(void *)) boot_update,
        .render = (void (*)(void *)) boot_render,
    };

您不创建结构仅将指针分配给具有地址(参考)的结构]复合文字& 需要得到这个文字的地址。

你必须记住,复合文字只有周围范围的生命周期。

struct SceneInterface *TitleAsScene = &(struct SceneInterface) {
    .update = (void (*)(void *)) title_update,
     .render = (void (*)(void *)) title_render,
};

可以读作

"TitleAsScene是一个指向struct SceneInterface的指针,其初始值为struct SceneInterface的地址构造如下..."

换句话说,指针是用您用成员初始化语句初始化的结构的地址初始化的。

您所指的语法是一个复合文字,似乎是强制转换后跟一个初始值设定项列表。它创建给定类型的临时对象。有问题的行然后获取该临时对象的地址并将其放置在指针中。

然而,在这里使用复合文字并没有多大意义。代码可以像这样轻松编写:

struct SceneInterface BootAsScene = {
    .update = (void (*)(void *)) boot_update,
    .render = (void (*)(void *)) boot_render,
};
struct SceneInterface TitleAsScene = {
    .update = (void (*)(void *)) title_update,
    .render = (void (*)(void *)) title_render,
};

struct Scene *bootScene = scene_create(boot, &BootAsScene);
struct Scene *titleScene = scene_create(title, &TitleAsScene);

但是这段代码还有另一个问题。函数指针被转换为不同的类型,随后通过该转换类型调用。通过不兼容的函数指针类型调用函数会触发 undefined behavior.

应更改函数以接受 void * 参数并将参数转换为函数内部的适当类型。