头文件中的static变量

C语言 码拜 9年前 (2016-04-05) 1513次浏览
在cal.h文件中是这样的:
#ifndef CAL_H
#define CAL_H
#define NUMBER “0”
static int test_include = 100;
void push(double);
double pop(void);
int getop(char[]);
int getch(void);
void ungetch(int);
#endif
在stack.c文件中是这样的:
#include “cal.h”
void push(double c)
{
test_include += 20;
}
在getop.c中是这样的:
#include “cal.h”
int getop(char s[])
{
test_include = 58;
return 0;
}
在getch.c中是这样的:
#include “cal.h”
int getch(void)
{
test_include -= 10;
return 0;
}
在main.c中是这样的:
#include “cal.h”
#include <stdio.h>
void main()
{
char s[10];
push(0);
printf(“%d\n”, test_include);
getch();
printf(“%d\n”, test_include);
getop(s);
printf(“%d\n”, test_include);
}
小弟单步调试,被调用的三个函数都能进去,并且在函数里面test_include的值是已经被改变了的。但是输出的结果如下:头文件中的static变量
小弟在发此贴之前对#include 和static的理解如下:
1、#include指令会将被include进来的文件拷贝一个副本,并且把副本引入。
2、static修饰外部变量,会将外部变量的作用域限制在本文件之内,而将其include的文件访问不到这个变量。
小弟的疑问是:
1、在三个文件的三个函数中都没报错,且在函数里面test_include的值已经被改变,然而,输出的test_include的值却没变。
2、假如去掉cal.h文件里static int test_include = 100;static其它地方不变,那么输出如下头文件中的static变量
三个文件引入的cal.h不是把副本引入么,但是为何三个函数修改的是同一个变量?
究竟这个#include和static的作用和机制是什么!
请各位前辈指点!
多谢!
解决方案

2

就绝对不可以在头文件里定义变量,不管能否加static
研究其出错细节,基本属浪费生命。

2

static 变量 不是只能在static函数中使用吗?
一般都是在头文件中用extern声明的,然后在c文件中定义。

2

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

2

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

2

即使在头文件里,进行了特殊处理,全局变量还是全局变量。
在大型项目中,非常容易出问题。
而且头文件中定义变量最好是用extern 而不是static ,这两者是有差异的!
static允许其他地方有重复,而extern不可以。
简单说就是,C/C++的文件都是单独编译的,每一个编译后的文件由连接器组成一个可执行文件。
对于static来说,每个引用:

Quote: 引用:

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

小弟还是对第二种输出结果(在头文件定义的变量被3个文件修改了)还是有疑惑。小弟的理解是这样的:#include将代码copy进来到那三个c文件,形成的临时文件中都各有各自的test_include呀,那么编译的时候应该编译的是copy(预编译)完成以后的临时文件,则,test_include应该是各自文件里面的,三个文件互不影响其它文件的test_include。

#include之后每个源文件编译之后的模块都有一个同名变量,没用static所以这个变量对其他源文件编译之后的模块就是可见的
本人不熟悉C语言中关于声明和定义的标准所以没有说,从结果来看似乎是你用的C编译器将这些源于同一个头文件的同名变量整合成一个变量了
在C++语言中,你这种写法直接通不过编译,报错“多个模块有同名全局变量”

2

第一次输出 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编译器应该编译不了了,命名冲突,两个变量用了同一个名字。

2

确定无疑,gcc编译器不能通过编译。理论上也不能通过编译。
应该是你的编译器蛋疼了。

2

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

1

引用:
Quote: 引用:

即使在头文件里,进行了特殊处理,全局变量还是全局变量。
在大型项目中,非常容易出问题。
而且头文件中定义变量最好是用extern 而不是static ,这两者是有差异的!
static允许其他地方有重复,而extern不可以。
简单说就是,C/C++的文件都是单独编译的,每一个编译后的文件由连接器组成一个可执行文件。
对于static来说,每个引用:

Quote: 引用:
Quote: 引用:
Quote: 引用:

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

小弟还是对第二种输出结果(在头文件定义的变量被3个文件修改了)还是有疑惑。小弟的理解是这样的:#include将代码copy进来到那三个c文件,形成的临时文件中都各有各自的test_include呀,那么编译的时候应该编译的是copy(预编译)完成以后的临时文件,则,test_include应该是各自文件里面的,三个文件互不影响其它文件的test_include。

#include之后每个源文件编译之后的模块都有一个同名变量,没用static所以这个变量对其他源文件编译之后的模块就是可见的
本人不熟悉C语言中关于声明和定义的标准所以没有说,从结果来看似乎是你用的C编译器将这些源于同一个头文件的同名变量整合成一个变量了
在C++语言中,你这种写法直接通不过编译,报错“多个模块有同名全局变量”

本人用的vc++6.0写的代码。C++本人没试过。

cal.h文件删除static后,clean一下工程,再重新编译,应该就编译不过了。
报错和C++都是一样的。


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明头文件中的static变量
喜欢 (0)
[1034331897@qq.com]
分享 (0)