【问题标题】:How can I define two global `const` variables to the same value in a C module?如何在 C 模块中将两个全局“const”变量定义为相同的值?
【发布时间】:2010-02-05 07:14:49
【问题描述】:

我在我的一个.c 文件中使用了一对全局变量,它们与两个不同的.h 文件中的一个extern 声明相匹配(好吧,一个.h 文件,以两种方式预处理) .一种是公用的,一种是私人使用的。两者都是const 变量。

我只想初始化我.c文件中的一个变量,然后将第二个变量赋值给相同的内容。以下是目前.c文件的相关内容:

struct List_methods const List = {
  .create         = List__create,
  .create_naughty = List__create_naughty,
  // …
};
struct List_methods const Paws__List = List;

... 以及对应的 .h:

#if defined(EXTERNALIZE)
# define  List_methods  Paws__List_methods
# define  List          Paws__List
#endif

// …

struct List_methods {
  list  (*create)         (void);
  list  (*create_naughty) (void);
  // …
} const extern List;

#if defined(EXTERNALIZE)
# undef   List_methods  Paws__List_methods
# undef   List          Paws__List
#endif

这里的目标是确保当.h 包含在定义的EXTERNALIZE 中时,包含文件可以访问Paws__List 变量,extern'd 可以访问我的.c 文件中的定义.但是,如果包含没有该定义,则他们可以访问extern'd List(我打算在我的内部文件中使用它,如果#includeer想要)。

但是,Paws__List = List 分配在我的编译器中爆炸,出现以下错误:

Source/Paws.o/list/list.c:32:40: error: initializer element is not a
      compile-time constant
struct List_methods const Paws__List = List;
                                       ^~~~

我正在寻求任何帮助以使这项工作如上所述(也就是说,在我的 .c 文件中为同一结构定义两个 const 名称,这样一个或另一个可以是由.h 标头引用。)

【问题讨论】:

  • Paws__List 旨在成为 List 的 副本?不是参考或某种别名?
  • 它旨在引用相同的东西。不过,它不应该是一个指针。即使用extern Paws__List 的代码应该得到与使用extern List 的代码相同的东西,只要两者都针对这个.c 文件进行编译。
  • 是否存在两者不应该相同的情况?
  • “我只想初始化我的.c文件中的一个变量,然后将第二个变量赋值给相同的内容”。如果它有帮助,编译器中发生的事情初始化,而不是赋值。我认为我不太了解这个问题,是什么阻止您在使用 Paws 版本的任何地方都执行#define Paws__List (List),并且类型名称也是如此?为什么要使用保留名称? ;-)
  • @elliottcable,双下划线是为编译器保留的,例如 C++ 编译器可能会使用它们进行名称修改

标签: c constants global-variables extern


【解决方案1】:

如果我对您的理解正确,您想定义一个接口(vtable)并且实现会因EXTERNALIZE而异:

我会走那条路:


/* header file */
/* define the interface */
typedef struct List_methods {
  list  (*create)         (void);
  list  (*create_naughty) (void);
  // …
} List_Methods;

const extern List_methods Paws_List; // note: double underscores are afaik not allowed
const extern List_methods Other_List; // take any name but List

#ifdef EXTERNALIZE
# define  List          Paws_List
#else
# define  List          Other_List
#end

重要的是结构是相同的类型,否则你不能分配一个给 其他。其次,我不会用别名覆盖符号。这只会在您想同时使用这两者时出现问题,例如在您的 .c 文件中。

【讨论】:

  • 不,这是倒退:我只想公开 一个 接口,但它是一个不同的接口,具体取决于EXTERNALIZE。具体来说,大多数针对我的库构建的人将包括Paws.h,它设置EXTERNALIZE,然后包括我的库中的其他标题。该文件设置了一个包含这些其他结构的结构,例如Paws.List.…。这意味着List 本身在该名称下不可用;相反,它以Paws__List 的形式提供,然后存储在Paws 结构下。
  • 但是,inside 我的库,(并且可选地,如果人们直接(单独)包含我的标题而不通过全局Paws.h),当.c 文件是单独编译,List 是自己定义的,就像我所有的其他命名空间一样;与上述相反。这使我可以维护两个 API:一个内部 API,由一组 const 变量(ListNumericString 等)组成……和一个外部 API,其中 一切 安全地存储在Paws 下(以避免人们在构建时发生冲突。)
  • 所以,所有这些都解释了......问题中描述的List.h 文件需要extern 一个List 定义(当包含在内部文件中时),或者extern一个Paws__List 定义(当包含在Paws.h 中时,它会设置EXTERNALIZE……然后将Paws__List 和朋友存储在extern'd Paws 变量中)。
猜你喜欢
  • 2021-06-26
  • 2011-03-01
  • 1970-01-01
  • 2014-06-16
  • 2017-02-23
  • 2015-01-02
  • 2013-07-21
  • 2020-07-19
  • 1970-01-01
相关资源
最近更新 更多