2

我正在寻找最好的方法来静态定义需要循环链接的 C/C++ 数据结构。例如,一棵树,其中孩子和父母都需要彼此的指针。

extern struct Op op_subops[4]; // fwd ref to children of ops

struct Op
{
    const char *name;
    struct Op  *parent;
    struct Op  *children;
};


struct Op ops[128] = {
    {"op",0,&op_subops[0]}
};

struct Op op_subops[4] = {
    {"subop1",&ops[1],0},
    {"subop2",&ops[1],0}
};

以上编译(g++ 5.2)。该extern关键字似乎允许我从opsinto创建一个前向引用ops_subops,而另一个方向自然而然地工作,因为ops之前ops_subops

我不喜欢的是,我更喜欢两个数组static(不在目标文件中创建公开可见的符号)。

我可以对其中一个方向使用整数索引,但这似乎有点做作,我宁愿让链接器为我解析地址。

任何人都有一个神奇的关键字来完成这项工作?

谢谢!

编辑:我需要避免使用 C++ 静态构造函数和前沿 C++17 扩展(遗憾的是)。而且我的方法需要独立于平台。

4

2 回答 2

2

在 C 或 C++ 中,底线是您不能在声明对象之前引用它,但是这两种语言都允许您编写“前向声明”来声明名称和(可能是不完整的)类型而不定义对象。对C比较熟悉,我会从这个角度回答;某些语义在 C++ 中可能有所不同。

在 C 中,您提供的代码的主要问题是它违反了数组的要求

只要指定了数组类型,元素类型就应该是完整的。

(C2011, 6.2.5/20)

这意味着虽然您可以在op_subops没有大小的情况下前向声明数组(在这种意义上使其类型不完整),但您不能在struct Op定义类型之前为它发出任何声明。这可以通过交换两个声明的位置来解决。

纠正了排序问题后,在 C 中声明两个数组都具有static链接是完全可以的;您只需要确保如果任何对象被多次声明(即op_subops)所有声明都同意其链接:

struct Op
{
    const char *name;
    struct Op  *parent;
    struct Op  *children;
};

static struct Op op_subops[4]; // fwd ref to children of ops

static struct Op ops[128] = {
    {"op",0,&op_subops[0]}
};

static struct Op op_subops[4] = {
    {"subop1",&ops[0],0},
    {"subop2",&ops[1],0}
};

如果您愿意,您可以省略op_subop第一个声明的长度,实际上我建议您这样做以避免在两个声明中保持长度一致。

尽管您要求“最佳 [已知] 方法”,但这将是一个意见问题,根据上下文进行着色,并且意见问题在这里是题外话。另一方面,在这种情况下,您似乎需要为孩子提供一个数组,所以我看不出在不改变类型的情况下还有什么其他选择。

于 2016-10-31T18:41:44.360 回答
1

当您正在寻找将您的数组声明为静态并且不能接受它们保持全局时,我假设您的意图是让两个数组都无法从外部世界访问。

想法1:只需(向前)声明静态数组:

我首先认为这将是前向声明的解决方案。这与 gcc 一起为 C 文件编译得很好:在线演示 1。但不幸的是,它既不能在 MSVC 上也不能在 C++ 上编译,因为它不是标准的:

    static struct Op op_subops[];  // compiler dependent - it's standard!

实际上它更简单:只需声明数组及其维度:

    static struct Op op_subops[4]; // as simple as that

在线演示 2

随后的初始化不会定义/重新定义数组;它指定要初始化的已声明数组。实际上,您可以将数组维度从初始化中排除。这次它在 gcc 和 MSVC 上编译:

    static struct Op op_subops[] = {  // [] or [4]
         ...
    };

想法 2:将两个数组放在一个未命名的命名空间中(仅限 C++)

然后您不再需要将这些项目作为静态的:未命名的命名空间确保其他编译单元无法引用这些对象

于 2016-10-31T18:13:02.507 回答