Linux下替代gcc __attribute__((selectany))的方法是什么?

4

我希望知道在Linux中是否有__attribute__((selectany))的替代方法?

我想定义类似于以下内容:

char * a[] = { "qwe", "zxc" };

在一个头文件中定义变量"a",并将其包含在许多.c文件中一起链接。因此,链接器会看到多个“a”的定义,因此无法链接。我读过这个属性(selectany),它将仅使用“a”的第一个定义,不幸的是,它仅适用于Microsoft Windows。那么问题来了:在Linux中有没有替代方法?
编辑:实际问题是:是否有一种方法可以指示链接器仅使用第一个出现的定义并忽略任何其他可能即使它们不同?我知道有很多定义数据的方法,我不是在寻找如何定义我的数据的解决方案,而是想知道是否有一种方法可以有多个定义并使链接器使用第一个出现的...

1
这很有趣,你能分享一下你最终想要实现什么吗?我理解这个问题,只是在阅读后感到好奇。 - Tim Post
我有一个枚举类型,其中包含一些类型(例如:STRING、INTEGER、FLOAT等)。正如您所知道的那样,这些类型的值是整数... 我需要这些类型的字符串表示,因此在这里就有了 char * type_names[] = { [STRING] = "string", ...},但是正如您所想象的那样,我需要将该定义放在头文件中的枚举类型附近,因此我将其设置为 static const char * [],并在其周围加上 #ifdef INCLUDE_TYPE_NAMES,但我很好奇是否有一种方法可以按照所描述的方式实现它。 - 0xAF
4个回答

7
我认为你正在寻找“弱”gcc属性。

这回答了实际问题。 - Brett Hale

2

首先,你应该明确地给它一个const属性:

char const * a[] = { "qwe", "zxc" };

修改字符串字面量会导致未定义的行为。那么,至少部分地回答你的问题。
除了以前的答案中声明它为 extern 的方法之外,第一种不推荐的处理方式是将数组声明为 static。然后,在使用该数组的每个编译单元中都会有一个数组副本。只要您不想修改数组内容(使指针指向不同的字符串),这很好,但会使代码变得冗长。
如果您只需要在函数范围内引用字符串,并且您有符合 C99 标准的编译器,可以尝试使用复合字面量:
#define MYARRAY ((char const*const[]){ "qwe", "zxc" })

你可以像预期的那样使用 readonly,例如 MYARRAY[1],任何优秀的编译器都应该能够优化这样的访问。


1
我本来想建议将它们声明为静态的,但我认为OP希望链接器忽略除“a”的第一个定义以外的所有内容。 - Tim Post
是的,这是我的第一个想法,将其定义为const和static,但正如你所提到的,它会产生与我拥有的对象文件(单元)一样多的副本,如果数据量很大并且对象文件很多,这是不好的... 但这是我能够链接多个数据定义的唯一方法,仍然不只是一个定义。至于第二个建议,如果编译器真的将其优化为一个副本,那么我会尝试一下,谢谢你的回答! - 0xAF

0

在头文件中声明如何:

extern char * a[] = { ... }

然后在一个c文件中定义实际的a[]:

char * a[] = { ... }

@Blagovest,这不是一个好主意,但如果你想保持多个数据类型同步...我知道有很多解决方案,但是否有属性或其他方法可以指示链接器在存在多个定义时仅使用一个定义? - 0xAF
是的。当您将变量声明为“extern”时,编译器会确保它只会在一个地方查找具体变量的内存位置,并且所有引用都指向同一个对象。 - Missaka Wijekoon
1
嗯,我知道了。gcc有一个叫做-multiply_defined的参数。你试过使用它来看看效果吗? - Missaka Wijekoon
@Misk,看起来-multiply_defined只适用于darwin,我找不到它的文档...更重要的是,在Linux GCC上它没有被识别...但还是谢谢你的尝试。 - 0xAF

0
为什么不直接在头文件中声明它,并在一个翻译单元中提供一个定义呢?

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接