本文共 1596 字,大约阅读时间需要 5 分钟。
转载原文地址:
#ifndef_XX_头文件.H
#define_XX_头文件.H intA; #endif那么,很糟糕的是,这里的intA是个全局变量的定义,所以如果这个头文件被多次引用的话,你的A会被重复定义
显然语法上错了。只不过有了这个#ifndef的条件编译,所以能保证你的头文件只被引用一次,不过也许还是会岔子,但若多个c文件包含这个头文件时还是会出错的,因为宏名有效范围仅限于本c源文件,所以在这多个c文件编译时是不会出错的,但在链接时就会报错,说你多处定义了同一个变量。该头文件被重复引用:
对于写好的a.h文件,对于变量A的赋值在A.CPP文件中进行
b.cpp:引用a.h,然后c.cpp引用b.h,此时c执行时,走到了b.h发现a已经被定义过了,那么就不会再次进行定义了,也就是a只被定义了一次。
但是如果对于b.cpp,c.cpp,d.cpp同时使用这一个头文件,在b中定义了一个a变量,此时这个宏定义在c中已经没有用了,所以在c.cpp中会再次定义这么一个a变量,d.cpp也会定义a变量。在编译时期不会报错,但是在链接时因为会找到多个变量a,此时会报错。
所以,ifndef只能解决一个头文件在同一个c文件中被重复定义的问题。除了这个c文件,其他的c文件还是有可能重复定义这个变量,导致链接过程中出错。
使用extern的好处是,extern 是对变量的声明而不是定义,这样可以避免变量的重复定义,最后只使用这样一个变量。
使用static:
修饰局部变量-->该函数内全局变量
修饰全局变量?
使用static修饰在头文件中修饰的变量,此时不会产生冲突(用static修饰的全局变量的作用域为定义的源文件),在多个源文件中引用该头文件,等于是在每个源文件中都定义了该变量一次,而且此变量仅在本源文件中有效,这样的使用方式不是本身想要的全局变量,也浪费了内存空间,不推荐使用 。
因为本身我们想使用全局变量是想多个文件同步使用一个变量的数据,也就是一个文件中的数据可以传递给另一个文件,所以一开始想到的是通过include加头文件的方式,但是这样每一个引用该头文件的源文件,都会再次定义一次该变量,也就是该变量已经不是我们想要共享的变量数据了。
所以想到的第一个解决办法通过extern,多个源文件共享一个变量数据。
第二就是通过static方式,但是这样的话,虽然不会引起重复定义,因为每个源文件都为该变量开辟出一块只属于该源文件的内存存放数据。但是这样也起不到全局变量的作用。
static修饰的全局变量的作用范围会被限制在声明的源文件内。
举个例子,
a.c
b.c
c.h
其中c.h被a.c,b.c引用, 而且c.h中定义了:
static int test = 0;
在编译的时候,a.c会和c.h一起编译, 然后b.c也会和c.h一起编译, 但是要注意, 编译器分别编译这两组文件的时候, 变量test会分别分配地址, 然后初始值也都为0;
这就意味着, 在a.c中如果调用了test, 其初始值为0;假设在a.c中test随后被修改为了2, 然后b.c中也调用test,这时test的初始值还是0, 而不是2!
如果不加上这个static,那么因为两个源文件都需要定义这个全局变量test,那么在链接过程中会出错,因为重复定义test。如果加上这个static,那么链接过程中不会出错,但是每个源文件都为这个变量分配了单独的空间,全局变量没有意义。最好的办法就是加上extern使得每个源文件都是引用,而不是重新定义从而出错。
最后这个问题跟ifndef解决的问题不一样,ifndef解决不了这个全局变量重复定义的问题,只能解决头文件在一个源文件中重复定义的问题,也解决不了多个源文件引用同一个头文件引起的重复定义问题。只能解决嵌套引用的问题