在 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,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,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) 而不是 { {1}})。

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

因此您必须从 static 的声明和定义中删除 const,并将代码添加到 gc_menu(或由 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