use*_*359 3 c struct pointers reference designated-initializer
我有一些有效的代码,但我不明白为什么。这是有问题的代码:
struct SceneInterface *TitleAsScene = &(struct SceneInterface) {
.update = (void (*)(void *)) title_update,
.render = (void (*)(void *)) title_render,
};
Run Code Online (Sandbox Code Playgroud)
我得到了函数指针和指定的初始值设定项,但是&(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;
}
Run Code Online (Sandbox Code Playgroud)
您所指的语法,似乎是一个强制转换后跟一个初始值设定项列表,是一个复合文字。它创建一个给定类型的临时对象。有问题的行然后获取该临时对象的地址并将其放置在指针中。
然而,在这里使用复合文字并没有多大意义。代码可以很容易地写成这样:
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);
Run Code Online (Sandbox Code Playgroud)
但是,此代码还有另一个问题。函数指针被转换为不同的类型,随后通过该转换类型调用。通过不兼容的函数指针类型调用函数会触发未定义的行为。
函数应该更改为接受void *
参数并将参数转换为函数内部的适当类型。