微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

我有一些有效的代码,但我不明白为什么。这是有问题的代码

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,};

    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 = {
    .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 * 参数并将该参数强制转换为函数内部的适当类型。

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

您不创建结构,只是将指针分配给具有复合文字地址(引用)的结构。需要 & 来获取此文字的地址。

你必须记住复合字面量只会有周围范围的生命周期。

,
LocalDateTime.now()

可以理解为

"struct SceneInterface *TitleAsScene = &(struct SceneInterface) { .update = (void (*)(void *)) title_update,}; 是指向 TitleAsScene 的指针,其初始值是 struct SceneInterface 的地址,构造如下..."

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。