在C ++中向前声明静态C结构体实例 [英] Forward declaring static C struct instances in C++

查看:169
本文介绍了在C ++中向前声明静态C结构体实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在写一个代码生成器,实际上是一个数据生成器,将生成这种形式的数据结构(显然实际的数据结构是更复杂):

I'm writing a code generator, well, actually a data generator that will produce data structures of this form (obviously the actual data structures are much more elaborate):

typedef struct Foo {
  int a;
  struct Foo* foo;
} Foo;

extern Foo f1;
extern Foo f2;

Foo f1 = {1, &f2};
Foo f2 = {2, &f1};

这是可移植的所有C和C ++编译器我试过。

This is portable for all C and C++ compilers I have tried.

我想转发这些struct实例为static,以便不会污染全局变量空间,如:

I would like to forward declare these struct instances as static so as not to pollute the global variable space, as in:

typedef struct Foo {
  int a;
  struct Foo* foo;
} Foo;

static Foo f1;
static Foo f2;

static Foo f1 = {1, &f2};
static Foo f2 = {2, &f1};

虽然这适用于gcc和所有C编译器,但上述代码不适用于C ++编译器,导致编译错误:

Although this works with gcc and probably all C compilers, the above code does not work with C++ compilers and results in a compile error:

error: redefinition of ‘Foo f1’
error: ‘Foo f1’ previously declared

我理解为什么会发生在C ++中。有没有简单的解决方法,不涉及使用代码在运行时实现相同的效果是移植到所有C ++编译器,而不诉诸使用C编译器编译某些文件?

I understand why this is happening in C++. Is there a simple workaround that does not involve using code at runtime to achieve the same effect that is portable to all C++ compilers without resorting to using a C compiler to compile certain files?

推荐答案

这似乎与Josh的答案有相似的效果,但复杂性较低:

This seems to have a similar effect to Josh's answer, but with less complexity:

#ifdef __cplusplus
namespace {
    extern Foo f1;
    extern Foo f2;

    Foo f1 = {1, &f2};
    Foo f2 = {2, &f1};
}
#else
    static Foo f1;
    static Foo f2;

    Foo f1 = {1, &f2};
    Foo f2 = {2, &f1};
#endif

当编译为C ++时,f1和f2的extern定义所述目标文件具有外部可链接符号;然而,因为它们在匿名命名空间内,所以符号被以不与另一个翻译单元的符号冲突的方式被破坏。

When compiled for C++, the extern definitions for f1 and f2 are exposed in the object file with an externally linkable symbol; however, because they are inside an anonymous namespace the symbols are mangled in such a way that they will not conflict with symbols from another translation unit.

使用宏魔法,你可以设置因此,只有一个地方,f1和f2被声明和定义,但如果这是机械生成的,可能没有太多理由这样做。

With macro magic you could set things up so there's only one place where f1 and f2 are declared and defined, but if this is being generated mechanically there's probably not much reason to do that.

有点像:

#ifdef __cplusplus
#define START_PRIVATES namespace {
#define END_PRIVATES   }
#define PRIVATE extern
#else
#define START_PRIVATES 
#define END_PRIVATES   
#define PRIVATE static
#endif

START_PRIVATES
    PRIVATE Foo f1;
    PRIVATE Foo f2;

    Foo f1 = {1, &f2};
    Foo f2 = {2, &f1};
END_PRIVATES

这篇关于在C ++中向前声明静态C结构体实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆