【问题标题】:gcc __attribute__((selectany)) alternative for linux?linux 的 gcc __attribute__((selectany)) 替代方案?
【发布时间】:2011-01-28 09:26:09
【问题描述】:

我想知道在 linux 中是否有 __attribute__((selectany)) 的替代品?

我想定义类似的东西:

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

在头文件中,并将其包含在许多将链接在一起的 .c 文件中。 因此链接器将看到多个“a”的定义,因此不会链接。我读过这个属性(selectany),它只使用第一次看到的“a”定义,不幸的是它只适用于ms windows。 所以问题是:在linux中是否有替代方法?

编辑:实际的问题是:有没有办法指示链接器只使用第一次看到的定义而忽略任何其他定义,即使它们不同? 我知道有很多方法可以定义我的数据,我不是在寻找如何定义我的数据的解决方案,而是我想知道是否有一种方法可以有多个定义并使链接器与第一个看到的一起工作。 ..

【问题讨论】:

  • 这很有趣,您能分享一下您最终要完成的工作吗?我明白这个问题,我只是在阅读后很好奇。
  • 我有一些类型的枚举(例如:STRING、INTEGER、FLOAT 等)。如您所知,类型的值是整数...我需要类型的字符串表示形式,所以这里出现了 char * type_names[] = { [STRING] = "string", ...},但您可以想象我需要在头文件中的枚举器附近进行该定义,因此我将其设为静态 const char * [],并在其周围加上#ifdef INCLUDE_TYPE_NAMES,但我很好奇是否有办法在所描述的(问题中)中完成它方式。

标签: c linux gcc linker multiple-definition-error


【解决方案1】:

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

【讨论】:

  • 这回答了实际问题。
【解决方案2】:

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

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

修改字符串文字会导致未定义的行为。然后回答你的问题,至少部分回答。

除了在前面的答案中声明它extern 的方法之外,第一个不推荐的方法是声明你的数组static。然后,您将在使用该数组的每个编译单元中拥有该数组的副本。只要您不想修改数组的内容(让指针指向不同的字符串),这很好,但会使您的代码有点炸毁。

如果您只需要在函数范围内引用字符串并且您有一个符合 C99 的编译器,您可以考虑使用 复合文字

#define MYARRAY ((char const*const[]){ "qwe", "zxc" })

然后你可以使用 readonly 正如你所期望的那样,像MYARRAY[1] 和任何体面的编译器应该能够优化这样的访问。

【讨论】:

  • 我本来建议将它们声明为静态的,但我认为 OP 希望链接器忽略除“a”的第一个定义之外的所有内容。
  • 是的,这是我的第一个想法,将其定义为 const 和 static,但正如您所提到的,它会制作与我拥有的目标文件(单位)一样多的副本,如果数据很大,目标文件很多……但这是我能够链接数据的多个定义的唯一方法,而不仅仅是一个定义。至于第二个建议似乎是个好主意,如果编译器真的优化到只有一个副本,我会试一试,谢谢你的回答!
【解决方案3】:

为什么不简单地在标题中声明它,并在一个翻译单元中提供一个定义?

【讨论】:

    【解决方案4】:

    如何在标题中声明为:

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

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

    char * a[] = { ... }
    

    【讨论】:

    • @Blagovest,这不是一个好主意,是的,但如果你想保持多种数据类型同步......我知道有很多解决方案,但是否有属性或其他方法来指示当有多个时,链接器只使用一个定义?
    • 是的。当您将变量声明为“extern”时,编译器会确保它只会在一次位置查找具体变量的内存位置,并且所有引用都将指向同一个对象。
    • 嗯,我明白了。 gcc 有一个名为 -multiply_defined 的参数。你有没有试过看看它是否有效?
    • @Misk,似乎 -multiply_defined 仅适用于 darwin,我找不到它的文档......甚至更多 - 它在 linux gcc 上无法识别......但感谢您的尝试。
    猜你喜欢
    • 2022-08-23
    • 2017-09-17
    • 2018-08-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多