C交叉编译器链接extern声明为静态?

时间:2013-10-03 10:16:11

标签: c linux gcc extern linkage

我正在经历一些奇怪的行为(好吧,我猜它有一个解释),同时试图将一些文件从Debian交叉编译到arm-linux目标,使用:

$ arm-linux-gnueabi-gcc --version

$ arm-linux-gnueabi-gcc (Debian 4.3.5-4) 4.3.5

编译时我收到以下错误消息:

dsblock1.c:167: error: non-static declaration of ‘HaveEventIterated_’ follows static declaration
ss2dym.c:778: error: previous declaration of ‘HaveEventIterated_’ was here

相应的行是:

ss2dym.c:778 :
extern long HaveEventIterated_;

"redeclaration" dsblock1.c:167:
long HaveEventIterated_=0;

所以这是我没有得到的东西: 根据我所知道的,变量首先声明为extern,是非静态的。

但是:“extern”声明在静态函数中。 所以我的猜测是,这是某种继承行为?!

以下是问题:     - 有人可以解释背景故事,如果我的猜测是正确的吗?     - 是否有一种简单的方法可以解决这个问题,例如:有一个棘手的编译器标志,允许嵌套的范围转移或其他一些魔术吗?

我知道很有可能创建一个标题并将所有这些extern声明放入中性空间,但我有数百个这样的错误和几个文件。我已经看到这个代码使用MSVC ++编译得很好(我知道其他范围限制,但我使用arm-g ++会遇到很多问题)因此必须有某种解决方案,比重写所有这些部分更容易...

顺便说一句:有一种简单的方法可以改变所有这些“重新声明”的范围,因为我在他们所有人面前都有一个宏:

MY_MACRO long HaveEventIterated_=0;

和atm我用-DMY_MACRO=

编译

Soooo有人吗? :)

1 个答案:

答案 0 :(得分:2)

extern关键字为标识符提供与先前可见声明相同的链接 1 ,如果没有先前的可见声明,则为外部链接。 (可以肯定的是,这是一种奇怪的语言怪癖。)

因此,问题最有可能是由于{em>第三个​​(或者我应该说是“第一个”)HaveEventIterated_声明,编译器在到达第778行之前到达ss2dym.c。第三个(或第一个)声明使用static关键字为标识符提供内部链接。第二个声明,extern,然后给出相同的变量内部链接,第三个 - 没有存储类关键字来指定链接 - 给出变量外部链接,导致错误。

这是一个简短的例子,可以重现问题(在不同的gcc中,但行为相同):

$ cat foo2.c
static int var;
extern int var;
int var = 0;
$ gcc -c foo2.c
foo2.c:3: error: non-static declaration of 'var' follows static declaration
foo2.c:2: error: previous declaration of 'var' was here

1 旁注:如果上一个可见声明具有 no 链接,则会获得外部链接。这仅在重新声明块内的变量时发生,其中该块外的变量具有自动持续时间,即,函数内的“本地”或“堆栈”变量:

void f(void) {
    int v;
    {
        extern int v;

这里有一个先前没有链接的可见声明,所以最里面的v有外部链接。如果在同一翻译单元中存在具有内部链接的v,则效果未定义。 (当然,没有人应该首先编写像f()这样的代码,无论如何:-))