2

在尝试将一些文件从 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”声明位于静态函数中。所以我的猜测是,这是某种继承的行为?!

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

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

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

MY_MACRO long HaveEventIterated_=0;

我用 atm 编译-DMY_MACRO=

有人吗?:)

4

1 回答 1

2

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

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

这是一个重现问题的简短示例(在不同的 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旁注:如果之前的可见声明没有链接,您将获得外部链接。这只发生在重新声明块内的变量时,该块外的变量具有自动持续时间,即,是函数内的“本地”或“堆栈”变量:

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

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

于 2013-10-03T10:43:36.460 回答