由实例浅析C中的static、extern、multiple definition of用法及陷阱

在JNI中,经常会遇到这种场景:想在一个.h文件中写一些全局变量,然后所有的cpp文件都能够使用。如下有个a.h文件:

/*
 * a.h
 *
 *  Created on: 2014-4-16
 *      Author: Administrator
 */

#ifndef A_H_
#define A_H_

int mAge = 0;
void setAge(int age);
int getAge();



#endif /* A_H_ */

里面很简单,有个变量mAge,两个接口,设置和读取。

下面是a.cpp文件:

/*
 * a.cpp
 *
 *  Created on: 2014-4-16
 *      Author: Administrator
 */

#include "a.h"
void setAge(int age){
	mAge = age;
}
int getAge(){
	return mAge;
}

然后有个main.cpp文件:

//============================================================================
// Name        : Test2.cpp
// Author      : yan
// Version     :
// Copyright   : Your copyright notice
// Description : Hello World in C++, Ansi-style
//============================================================================

#include <iostream>
#include "a.h"
using namespace std;

int main() {
	cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
	setAge(22);
	cout<<"age = "<<getAge()<<endl;
	return 0;
}
编译后报错:

E:\WorkSpaces\Eclipse_MinGW_C\Test2\Debug/../src/Test2.cpp:12: multiple definition of `main'
src\main.o:E:\WorkSpaces\Eclipse_MinGW_C\Test2\Debug/../src/main.cpp:13: first defined here
collect2.exe: error: ld returned 1 exit status
Build error occurred, build is stopped

报multiple definition of的错误,解决方法是将变量搞成static。搞成static确实不报错了,但这里却隐藏着一个天大的陷阱:

main.cpp如下:

#include <iostream>
#include "a.h"
using namespace std;

int main() {
	cout << "!!!Hello World!!!" << endl; // prints !!!Hello World!!!
	setAge(22);
	cout<<"age = "<<mAge<<endl;
	setAge(555);
	cout<<"age = "<<getAge()<<endl;
	return 0;
}

打印出来的结果是这样的:

!!!Hello World!!!
age = 0
age = 555

即虽然set成22了但是你访问的话,直接拿来用mAge仍然是初始化的0.而如果使用get接口来访问的数值是正确的。原因是:按书上说,static变量和一般全局变量一样,都存储在静态存储区。但static限定了变量访问权限,只能让本文件访问,为什么搞成static里,在main里有可以直接访问了?原因是static的变量是在h文件而非cpp文件中声明的。编译的过程中,include的东西类似直接覆盖的。所以直接访问mAge得到的是初始化的值,不光怎么set都没用。这着实是个陷阱啊!!!

事实上这样做也是不太安全的,更多时变量都在cpp文件声明。因此更加安全的方法是:

1、变量声明在cpp里,声明成普通的类型。然后通过set和get的方法进行设定和访问。

2、变量声明在cpp里,然后在h文件里将同样的变量声明成extern int mAge,这样所有包含h文件的既可以直接访问mAge。

3、static和extern是克星,一旦cpp文件里变量声明成static,那么在h文件里就不能extern了。

4、也可以h文件里声明普通变量,cpp里extern,但不推荐。变量还是在cpp里的好。

至少include “***.cpp”这种馊主意一般不要采用。

参考:

http://bbs.csdn.net/topics/390626289?page=1

http://blog.csdn.net/luo6620378xu/article/details/8511312

       





  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值