我正在经历一些奇怪的行为(好吧,我猜它有一个解释),同时试图将一些文件从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有人吗? :)
答案 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()
这样的代码,无论如何:-))