静态声明m遵循非静态声明

我正在尝试一个小例子来了解静态外部变量及其用途。 静态变量属于局部范围,外部变量属于全局范围。

static5.c

#include #include "static5.h" static int m = 25; int main(){ func(10); return 0; } 

static5.h

 #include int func(val){ extern int m; m = m + val; printf("\n value is : %d \n",m); } 

gcc static5.c static5.h

o / p:

 static5.c:3: error: static declaration of m follows non-static declaration static5.h:3: note: previous declaration of m was here 

EDITED

正确的程序:

 ac: #include #include "a1_1.h" int main(){ func(20); return 0; } a1.h: static int i = 20; a1_1.h: #include "a1.h" int func(val){ extern int i; i = i + val; printf("\ni : %d \n",i); } 

这很好用。 但是这被编译成一个单独的编译单元。 因此能够访问静态变量。 在编译单元中,我们不能通过使用extern变量来使用静态变量。

记住这一点(引用Eli Bendersky):

  • 函数内的静态变量在调用之间保持其值。
  • 静态全局变量或函数仅在其声明的文件中“看到”

在你的代码中, static int m = 25; 表示m范围仅限于该文件 ,也就是说,它只在static5.c可见,而在其他地方不可见。

如果你想在static5.c之外使用mstatic5.c确保从变量声明中删除关键字static

有关更典型的解释以及示例,请参阅Eli Bendersky的回答

编辑:(根据Klas的建议) **实际范围是编译单元,而不是源文件。 编译单元是文件在预处理器步骤之后的样子

static有一个非常简单的逻辑。 如果变量是static ,则意味着它是一个全局变量,但它的范围仅限于定义它的位置(即仅在那里可见)。 例如:

  • 函数外部:全局变量,但仅在文件中可见(实际上,编译单元)
  • 函数内部:全局变量,但仅在函数内可见
  • (C ++)一个类:全局变量,但只对类可见

现在让我们看看C11标准中关于staticextern (强调我的)的内容:

6.2.2.3

如果对象或函数的文件范围标识符的声明包含存储类说明符static ,则标识符具有内部链接。

6.2.2.4

对于在该标识符的先前声明可见的范围内使用存储类说明符extern声明的标识符, 如果先前声明指定内部或外部链接,则后面声明中的标识符的链接与链接相同在先前声明中指明。 如果没有先前声明可见,或者先前声明未指定链接,则标识符具有外部链接。

6.2.2.7

如果在翻译单元中,同一标识符同时出现内部和外部链接,则行为未定义。

所以标准说首先,如果你有:

 static int m; extern int m; 

然后第二个声明(使用extern )会考虑第一个,最后m仍然是static

但是,在任何其他情况下,如果存在具有内部和外部链接的声明,则行为未定义。 这实际上只留下了一个选项:

 extern int m; static int m; 

static声明前的extern声明。 gcc非常好,可以在这种未定义行为的情况下给你错误。

问题完全如错误消息中所述。 m被声明为普通的int但后来被定义为static int

extern告诉编译器/链接器在全局变量表中查找变量。

static (在functon之外)告诉编译器从全局变量表中排除变量。

你看到了冲突吗?

要解决此问题,请从定义中删除static关键字,或将定义移到包含static5.h

应该注意的是,您设计文件的方式不是最佳做法。 包含文件通常不包含函数。

在声明m时删除关键字static,错误将被删除,您将能够得到答案为50. static关键字使范围限制在文件中。