首页 > 解决方案 > 在 const 表达式中声明指向结构的指针

问题描述

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

为简单起见,mcl_items结构有一个虚拟方法 ( push),它将在其中运行gc_menu_add_item并分配给gc_menu静态空间。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,而不是定义中定义的 0 new_mcl_items

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

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

标签: cmemory-managementstaticdynamic-memory-allocationcalloc

解决方案


您已经初始化gc_menu.itemsnew_mcl_items,即指向函数的指针new_mcl_items(它应该给您一个警告,因为它是 typemcl_items *(*)(void)而不是mcl_items *)。

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

因此,您必须const从 的声明和定义中删除 ,并向(或由 调用的某些函数等)gc_menu添加代码以在运行时进行初始化。mainmaingc_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();
    // ...
}

推荐阅读