user-0 提问: 头文件中的static变量

回复:
user: user-1
content: baichi4141 讲的准确清晰，赞一个。

user: user-2
content: 引用 10 楼 M_o_n_e_y 的回复:[quote=引用 9 楼 baichi4141 的回复:] [quote=引用 8 楼 M_o_n_e_y 的回复:] [quote=引用 3 楼 baichi4141 的回复:] 楼主有一个基本概念没有理解，就是“预编译”和“编译”的区别 说的简单一点，编译是把源代码变成机器命令，预编译则是对源代码进行一些简单处理，这是完全独立的两个阶段 #include是预编译指令，作用是把指定文件的内容复制到当前文件当前行处 static是一个关键字，它的作用由语言标准规定，在编译时起到特定的作用 由此可以看出，static跟#include完全没有任何关系，在编译器编译源代码前，#include就已经完成其任务，编译器在处理static时，根本不知道当前这行代码是否被#include过多少次  所以“static修饰外部变量，会将外部变量的作用域限制在本文件之内，而将其include的文件访问不到这个变量”这个想法是错误的，static限定的“本文件”是“所有预编译指令执行后的文件”。如果你在一个头文件里定义了static全局变量，在几个源文件中包含这个头文件，结果就是这几个源文件分别都有了一个static全局变量 这就是不管你在其他几个源文件里怎么改，负责输出的那个源文件输出的值永远不变的原因，因为这几个源文件都有一个叫这个名字的变量，这几个变量彼此之间没有任何关系小弟还是对第二种输出结果（在头文件定义的变量被3个文件修改了）还是有疑惑。小弟的理解是这样的：#include将代码copy进来到那三个c文件，形成的临时文件中都各有各自的test_include呀，那么编译的时候应该编译的是copy（预编译）完成以后的临时文件，则，test_include应该是各自文件里面的，三个文件互不影响其它文件的test_include。[/quote] #include之后每个源文件编译之后的模块都有一个同名变量，没用static所以这个变量对其他源文件编译之后的模块就是可见的 我不熟悉C语言中关于声明和定义的标准所以没有说，从结果来看似乎是你用的C编译器将这些源于同一个头文件的同名变量整合成一个变量了 在C++语言中，你这种写法直接通不过编译，报错“多个模块有同名全局变量”[/quote]我用的vc++6.0写的代码。C++我没试过。[/quote]  cal.h文件删除static后，clean一下工程，再重新编译，应该就编译不过了。 报错和C++都是一样的。

user: user-3
content: 引用 11 楼 M_o_n_e_y 的回复:[quote=引用 5 楼 Adol1111 的回复:] 即使在头文件里，进行了特殊处理，全局变量还是全局变量。 在大型项目中，非常容易出问题。  而且头文件中定义变量最好是用extern 而不是static ，这两者是有差异的！！  static允许其他地方有重复，而extern不可以。  简单说就是，C/C++的文件都是单独编译的，每一个编译后的文件由连接器组成一个可执行文件。 对于static来说，每个引用该头文件的编译单元都允许有一份，但组成的最终文件不冲突。 而extern来说，是完全共享的，所有引用都是外部的，所以a文件改了，b文件也会受影响。请看8楼和3楼，然后指教小弟，为何两次输出的结果是如此。谢谢。[/quote] 都说了说static的作用域是本文件了，你在main.c以外的文件里修改这个变量，是不影响main.c中的test_include 所以最后输出结果都是相同的。 如果你想看到变化的话，改成extern（extern不能再定义时初始化，不然extern就无效了，头文件声明，在main.c中赋值）

user: user-4
content: 每个文件 #include "cal.h" 后都定义了 static	int	test_include = 100;  所以互不影响。  如 1F 所说不应该使用这种写法，哪个文件要用static变量就在哪个文件定义，不应放入头文件

user: user-5
content: 确定无疑，gcc编译器不能通过编译。理论上也不能通过编译。 应该是你的编译器蛋疼了。

user: user-5
content: 第一次输出 100 100 100是因为两个文件中有各自的 “test_include” 变量，因为你加了static，所以每个文件“stack.c”“main.c”访问的是自己的“test_include”变量。你调用的push、pop改变了stack.c中的test_include变量，没有改变main.c中的！ 如果你把输出函数写在stack.c中，然后在main.c中调用，你就会发现输出变化了。  至于去掉static以后，为什么你还能编译，这个我不能理解。在gcc编译器应该编译不了了，命名冲突，两个变量用了同一个名字。

user: user-0
content: 引用 3 楼 baichi4141 的回复:楼主有一个基本概念没有理解，就是“预编译”和“编译”的区别 说的简单一点，编译是把源代码变成机器命令，预编译则是对源代码进行一些简单处理，这是完全独立的两个阶段 #include是预编译指令，作用是把指定文件的内容复制到当前文件当前行处 static是一个关键字，它的作用由语言标准规定，在编译时起到特定的作用 由此可以看出，static跟#include完全没有任何关系，在编译器编译源代码前，#include就已经完成其任务，编译器在处理static时，根本不知道当前这行代码是否被#include过多少次  所以“static修饰外部变量，会将外部变量的作用域限制在本文件之内，而将其include的文件访问不到这个变量”这个想法是错误的，static限定的“本文件”是“所有预编译指令执行后的文件”。如果你在一个头文件里定义了static全局变量，在几个源文件中包含这个头文件，结果就是这几个源文件分别都有了一个static全局变量 这就是不管你在其他几个源文件里怎么改，负责输出的那个源文件输出的值永远不变的原因，因为这几个源文件都有一个叫这个名字的变量，这几个变量彼此之间没有任何关系小弟还是对第二种输出结果（在头文件定义的变量被3个文件修改了）还是有疑惑。小弟的理解是这样的：#include将代码copy进来到那三个c文件，形成的临时文件中都各有各自的test_include呀，那么编译的时候应该编译的是copy（预编译）完成以后的临时文件，则，test_include应该是各自文件里面的，三个文件互不影响其它文件的test_include。

user: user-0
content: 引用 2 楼 haolly 的回复:static 变量 不是只能在static函数中使用吗？ 一般都是在头文件中用extern声明的，然后在c文件中定义。static 变量 不是只能在static函数中使用吗？这句话何解？

user: user-0
content: 引用 1 楼 user-9 的回复:就绝对不可以在头文件里定义变量，不管是否加static 研究其出错细节，基本属浪费生命。请指教！

user: user-0
content: 引用 5 楼 Adol1111 的回复:即使在头文件里，进行了特殊处理，全局变量还是全局变量。 在大型项目中，非常容易出问题。  而且头文件中定义变量最好是用extern 而不是static ，这两者是有差异的！！  static允许其他地方有重复，而extern不可以。  简单说就是，C/C++的文件都是单独编译的，每一个编译后的文件由连接器组成一个可执行文件。 对于static来说，每个引用该头文件的编译单元都允许有一份，但组成的最终文件不冲突。 而extern来说，是完全共享的，所有引用都是外部的，所以a文件改了，b文件也会受影响。请看8楼和3楼，然后指教小弟，为何两次输出的结果是如此。谢谢。

user: user-0
content: 引用 9 楼 baichi4141 的回复:[quote=引用 8 楼 M_o_n_e_y 的回复:] [quote=引用 3 楼 baichi4141 的回复:] 楼主有一个基本概念没有理解，就是“预编译”和“编译”的区别 说的简单一点，编译是把源代码变成机器命令，预编译则是对源代码进行一些简单处理，这是完全独立的两个阶段 #include是预编译指令，作用是把指定文件的内容复制到当前文件当前行处 static是一个关键字，它的作用由语言标准规定，在编译时起到特定的作用 由此可以看出，static跟#include完全没有任何关系，在编译器编译源代码前，#include就已经完成其任务，编译器在处理static时，根本不知道当前这行代码是否被#include过多少次  所以“static修饰外部变量，会将外部变量的作用域限制在本文件之内，而将其include的文件访问不到这个变量”这个想法是错误的，static限定的“本文件”是“所有预编译指令执行后的文件”。如果你在一个头文件里定义了static全局变量，在几个源文件中包含这个头文件，结果就是这几个源文件分别都有了一个static全局变量 这就是不管你在其他几个源文件里怎么改，负责输出的那个源文件输出的值永远不变的原因，因为这几个源文件都有一个叫这个名字的变量，这几个变量彼此之间没有任何关系小弟还是对第二种输出结果（在头文件定义的变量被3个文件修改了）还是有疑惑。小弟的理解是这样的：#include将代码copy进来到那三个c文件，形成的临时文件中都各有各自的test_include呀，那么编译的时候应该编译的是copy（预编译）完成以后的临时文件，则，test_include应该是各自文件里面的，三个文件互不影响其它文件的test_include。[/quote] #include之后每个源文件编译之后的模块都有一个同名变量，没用static所以这个变量对其他源文件编译之后的模块就是可见的 我不熟悉C语言中关于声明和定义的标准所以没有说，从结果来看似乎是你用的C编译器将这些源于同一个头文件的同名变量整合成一个变量了 在C++语言中，你这种写法直接通不过编译，报错“多个模块有同名全局变量”[/quote]我用的vc++6.0写的代码。C++我没试过。

user: user-6
content: 引用 8 楼 M_o_n_e_y 的回复:[quote=引用 3 楼 baichi4141 的回复:] 楼主有一个基本概念没有理解，就是“预编译”和“编译”的区别 说的简单一点，编译是把源代码变成机器命令，预编译则是对源代码进行一些简单处理，这是完全独立的两个阶段 #include是预编译指令，作用是把指定文件的内容复制到当前文件当前行处 static是一个关键字，它的作用由语言标准规定，在编译时起到特定的作用 由此可以看出，static跟#include完全没有任何关系，在编译器编译源代码前，#include就已经完成其任务，编译器在处理static时，根本不知道当前这行代码是否被#include过多少次  所以“static修饰外部变量，会将外部变量的作用域限制在本文件之内，而将其include的文件访问不到这个变量”这个想法是错误的，static限定的“本文件”是“所有预编译指令执行后的文件”。如果你在一个头文件里定义了static全局变量，在几个源文件中包含这个头文件，结果就是这几个源文件分别都有了一个static全局变量 这就是不管你在其他几个源文件里怎么改，负责输出的那个源文件输出的值永远不变的原因，因为这几个源文件都有一个叫这个名字的变量，这几个变量彼此之间没有任何关系小弟还是对第二种输出结果（在头文件定义的变量被3个文件修改了）还是有疑惑。小弟的理解是这样的：#include将代码copy进来到那三个c文件，形成的临时文件中都各有各自的test_include呀，那么编译的时候应该编译的是copy（预编译）完成以后的临时文件，则，test_include应该是各自文件里面的，三个文件互不影响其它文件的test_include。[/quote] #include之后每个源文件编译之后的模块都有一个同名变量，没用static所以这个变量对其他源文件编译之后的模块就是可见的 我不熟悉C语言中关于声明和定义的标准所以没有说，从结果来看似乎是你用的C编译器将这些源于同一个头文件的同名变量整合成一个变量了 在C++语言中，你这种写法直接通不过编译，报错“多个模块有同名全局变量”

user: user-3
content: 即使在头文件里，进行了特殊处理，全局变量还是全局变量。 在大型项目中，非常容易出问题。  而且头文件中定义变量最好是用extern 而不是static ，这两者是有差异的！！  static允许其他地方有重复，而extern不可以。  简单说就是，C/C++的文件都是单独编译的，每一个编译后的文件由连接器组成一个可执行文件。 对于static来说，每个引用该头文件的编译单元都允许有一份，但组成的最终文件不冲突。 而extern来说，是完全共享的，所有引用都是外部的，所以a文件改了，b文件也会受影响。

user: user-7
content: 1.首先最好不要在头文件中定义变量，除非其它模块需要调用，即是用extern定义，告诉编译器这个变量是可以被其它模块调用。 2.static是模块内的调用，不允许外部调用

user: user-6
content: 楼主有一个基本概念没有理解，就是“预编译”和“编译”的区别 说的简单一点，编译是把源代码变成机器命令，预编译则是对源代码进行一些简单处理，这是完全独立的两个阶段 #include是预编译指令，作用是把指定文件的内容复制到当前文件当前行处 static是一个关键字，它的作用由语言标准规定，在编译时起到特定的作用 由此可以看出，static跟#include完全没有任何关系，在编译器编译源代码前，#include就已经完成其任务，编译器在处理static时，根本不知道当前这行代码是否被#include过多少次  所以“static修饰外部变量，会将外部变量的作用域限制在本文件之内，而将其include的文件访问不到这个变量”这个想法是错误的，static限定的“本文件”是“所有预编译指令执行后的文件”。如果你在一个头文件里定义了static全局变量，在几个源文件中包含这个头文件，结果就是这几个源文件分别都有了一个static全局变量 这就是不管你在其他几个源文件里怎么改，负责输出的那个源文件输出的值永远不变的原因，因为这几个源文件都有一个叫这个名字的变量，这几个变量彼此之间没有任何关系

user: user-8
content: static 变量 不是只能在static函数中使用吗？ 一般都是在头文件中用extern声明的，然后在c文件中定义。

user: user-9
content: 就绝对不可以在头文件里定义变量，不管是否加static 研究其出错细节，基本属浪费生命。