在 const 表达式中声明一个指向结构的指针

Declare a pointer to structure in const expression

我是 C 的新手,还不能自由浏览我的程序内存。无论如何,我正在创建一个静态内存数据类型(gc_menu),它应该包含一个指向在执行时创建的结构(mcl_items)的指针。

为简单起见,mcl_items 结构有一个虚拟方法 (push),它将在 gc_menu_add_item 内部 运行 并分配给 gc_menu 静态 space。 push 将菜单​​项名称(字母)和方法保存到 mcl_item 虚拟对象。

mcl_items.h代码:

[...]

typedef struct Items_t {
  int8_t size;
  char names[64];
  void (*methods[64])();
  // Interface
  void (*push)(struct Items_t *self, char c, void (*method)());
}mcl_items;

mcl_items *new_mcl_items();
void mcl_items_push(mcl_items *self, char c, void (*method)());

mcl_items.c代码:

[...]
#include "mcl_items.h"

mcl_items *new_mcl_items() {
  fprintf(stderr, "MCL_Items: Generating a new set of mcl_items..");
  // Build a virtual object
  mcl_items *items    = calloc(1, sizeof(struct Items_t));
  items->push         = mcl_items_push;
  // Set data
  items->size         = 0;
  return items;
}

void mcl_items_push(mcl_items *self, char c, void (*method)()) {
  fprintf(stderr, "MCL_Items: pushing a new item..");
  self->names[self->size] = c;
  self->methods[self->size] = method;
  self->size ++;
}

gc_menu.h代码:

#include "items.h"

typedef struct {
  // Interface
  void (*add_item)(char c, void (*method)());
  // Data
  mcl_items *items;
}__gc_menu;

extern __gc_menu const gc_menu;

gc_menu.c代码:

static void gc_menu_add_item(char c, void (*method)) {
  fprintf(stderr, "GC_Menu: Passing an new item..");
  fprintf(stderr, "length = %i\n", gc_menu.items->size);
  gc_menu.items->push(gc_menu.items, c, method);
}

__gc_menu const gc_menu = {gc_menu_add_item,    // Virtual methods
                           new_mcl_items};      // Data

在调用 gc_menu.add_item 之后发生分段错误并且 gc_menu.items->size 等于 72,而不是 new_mcl_items.

定义中定义的 0

main.c代码:

gc_menu.add_item('q', xw->end(xw));
GC_Menu: Passing an new item..length = 72
[1]    66021 segmentation fault (core dumped)  ./3D_scean

那我做错了什么?为什么我的 gc_menu.items 实例中写入了如此奇怪的数据?

您已将 gc_menu.items 初始化为 new_mcl_items,即指向函数 new_mcl_items 的指针(它应该给您一个警告,因为它是 mcl_items *(*)(void) 类型并且不是 mcl_items *).

看起来你想要的实际上是 调用 函数 new_mcl_items() 并将 gc_menu.items 设置为 new_mcl_items() returns。你不能用初始化器来做到这一点;全局或 static 对象的初始值设定项必须在编译或 link 时已知。标准 C 没有“构造函数”。

因此您必须从 gc_menu 的声明和定义中删除 const,并向 main 添加代码(或 main 调用的某些函数等)在 运行 时初始化 gc_menu.items

gc_menu.h:

extern __gc_menu gc_menu;

gc_menu.c:

__gc_menu gc_menu = { 
    gc_menu_add_item,
    NULL // or whatever else you like
};

main.c 或者随便你怎么称呼它:

int main(void) {
    // ...
    gc_menu.items = new_mcl_items();
    // ...
}