在头文件中定义变量以及static变量意味着什么?全局变量要如何正确使用?关键字extern要怎么用?

本文主要是介绍在头文件中定义变量以及static变量意味着什么?全局变量要如何正确使用?关键字extern要怎么用?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

CPU型号:Intel(R) Core(TM) i5-2450M 

系统:windows 10

IDE:Microsoft Visual C++ 6.0(下文中简称VC)

制图软件:Photoshop cs5

预备知识:头文件和其对应的实现文件.c或者.cpp可视为一个模块)


今天在测试static关键字的时候,发现了一个奇怪的现象,也就是在头文件中定义static变量竟然可以被包含这个头文件的其他模块引用!下面是测试代码:

头文件A.h

//A.h
#ifndef _A_H
#define _A_H
static int a = 5;
#endif
main函数main.cpp

#include <IOSTREAM>
#include "A.h"
using namespace std;
int main(void)
{cout<<"a="<<a<<endl;	return 0;
}
编译没有问题!!!运行也没有问题!!!还能显示出结果a=5,说好的static变量对其他模块隐藏呢!!!???怎么会这样???难道static变量放在头文件中意义就变了吗??

新建一个模块再次进行测试

模块B.h

#ifndef _B_H
#define _B_H
void Bfun(void);
#endif
模块B的实现代码B.cpp

#include "B.h"
#include "A.h"
#include <IOSTREAM>
using namespace std;
void Bfun(void)
{a++;cout<<"Bfun: a="<<a<<endl;
}
修改后的main.cpp

#include <IOSTREAM>
#include "A.h"
#include "B.h"
using namespace std;
int main(void)
{Bfun();cout<<"main: a="<<a<<endl;	return 0;
}
运行结果:



怀疑人生了有没有????!!!static变量又不能对其他模块进行隐藏,又不是全局变量,这又是怎么回事?打印下地址看看


两个不一样的地址,说明a不是全局变量,也就是说定义在头文件里的static变量,被其他模块每包含一次就申请一次内存!

如果把A.h中的static去掉呢?
编译运行会发现以下错误提示:

static int a去掉static后就变成全局变量了,此时又提示重复定义,由此可见,定义在头文件中的全局变量,每被#include一次,就会被声明定义一次。全局变量#include多次会出错,而static变量被#include多次会生成多个局部变量,但这并不是我们想要的结果!

如果把变量声明在.cpp文件中呢?

A.h

#ifndef _A_H
#define _A_H#endif
A.cpp

#include "A.h"
static int a = 5;
main.cpp

#include <IOSTREAM>
#include "A.h"
using namespace std;int main(void)
{cout<<a<<endl;	return 0;
}
编译后会提示:

error C2065: 'a' : undeclared identifier

这样的结果刚好也符合static变量对其他模块是不可见的特性。

去掉static后,再进行测试。


结果怎么又是未定义error C2065: 'a' : undeclared identifier


原来是引用全局变量要在引用的模块内加extern关键字!


再在main.cpp的main函数前加上extern int a ;即可对int a进行引用。修改代码:

A.h

#ifndef _A_H
#define _A_H#endif
A.cpp

#include "A.h"
int a = 5;

B.h

#ifndef _B_H
#define _B_H
void Bfun(void);
#endif
B.cpp

#include "B.h"
#include "A.h"
#include <IOSTREAM>
using namespace std;
extern int a;
void Bfun(void)
{a++;cout<<"Bfun: a="<<a<<",addr="<<&a<<endl;
}
main.cpp

#include <IOSTREAM>
#include "A.h"
#include "B.h"
using namespace std;
extern int a;
int main(void)
{Bfun();cout<<"main: a="<<a<<",addr="<<&a<<endl;return 0;
}
运行结果:

在模块B和main函数中,全局变量a的地址和值保持一致!


因此!


变量不要在头文件中定义,要在实现文件中定义!


全部变量的引用要加关键字extern!

这篇关于在头文件中定义变量以及static变量意味着什么?全局变量要如何正确使用?关键字extern要怎么用?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/979642

相关文章

C语言中联合体union的使用

本文编辑整理自: http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=179471 一、前言 “联合体”(union)与“结构体”(struct)有一些相似之处。但两者有本质上的不同。在结构体中,各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间, 一个联合变量

[职场] 护理专业简历怎么写 #经验分享#微信

护理专业简历怎么写   很多想成为一名护理方面的从业者,但是又不知道应该怎么制作一份简历,现在这里分享了一份护理方面的简历模板供大家参考。   蓝山山   年龄:24   号码:12345678910   地址:上海市 邮箱:jianli@jianli.com   教育背景   时间:2011-09到2015-06   学校:蓝山大学   专业:护理学   学历:本科

Tolua使用笔记(上)

目录   1.准备工作 2.运行例子 01.HelloWorld:在C#中,创建和销毁Lua虚拟机 和 简单调用。 02.ScriptsFromFile:在C#中,对一个lua文件的执行调用 03.CallLuaFunction:在C#中,对lua函数的操作 04.AccessingLuaVariables:在C#中,对lua变量的操作 05.LuaCoroutine:在Lua中,

C# 中变量未赋值能用吗,各种类型的初始值是什么

对于一个局部变量,如果未赋值,是不能使用的 对于属性,未赋值,也能使用有系统默认值,默认值如下: 对于 int 类型,默认值是 0;对于 int? 类型,默认值是 null;对于 bool 类型,默认值是 false;对于 bool? 类型,默认值是 null;对于 string 类型,默认值是 null;对于 string? 类型,哈哈,没有这种写法,会出错;对于 DateTime 类型,默

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值:简单的数据即基础数据类型,按值访问。 引用值:由多个值构成的对象即复杂数据类型,按引用访问。 动态属性 对于引用值而言,可以随时添加、修改和删除其属性和方法。 let person = new Object();person.name = 'Jason';person.age = 42;console.log(person.name,person.age);//'J

Vim使用基础篇

本文内容大部分来自 vimtutor,自带的教程的总结。在终端输入vimtutor 即可进入教程。 先总结一下,然后再分别介绍正常模式,插入模式,和可视模式三种模式下的命令。 目录 看完以后的汇总 1.正常模式(Normal模式) 1.移动光标 2.删除 3.【:】输入符 4.撤销 5.替换 6.重复命令【. ; ,】 7.复制粘贴 8.缩进 2.插入模式 INSERT

Java面试八股之怎么通过Java程序判断JVM是32位还是64位

怎么通过Java程序判断JVM是32位还是64位 可以通过Java程序内部检查系统属性来判断当前运行的JVM是32位还是64位。以下是一个简单的方法: public class JvmBitCheck {public static void main(String[] args) {String arch = System.getProperty("os.arch");String dataM

电脑不小心删除的文件怎么恢复?4个必备恢复方法!

“刚刚在对电脑里的某些垃圾文件进行清理时,我一不小心误删了比较重要的数据。这些误删的数据还有机会恢复吗?希望大家帮帮我,非常感谢!” 在这个数字化飞速发展的时代,电脑早已成为我们日常生活和工作中不可或缺的一部分。然而,就像生活中的小插曲一样,有时我们可能会在不经意间犯下一些小错误,比如不小心删除了重要的文件。 当那份文件消失在眼前,仿佛被时间吞噬,我们不禁会心生焦虑。但别担心,就像每个问题

Lipowerline5.0 雷达电力应用软件下载使用

1.配网数据处理分析 针对配网线路点云数据,优化了分类算法,支持杆塔、导线、交跨线、建筑物、地面点和其他线路的自动分类;一键生成危险点报告和交跨报告;还能生成点云数据采集航线和自主巡检航线。 获取软件安装包联系邮箱:2895356150@qq.com,资源源于网络,本介绍用于学习使用,如有侵权请您联系删除! 2.新增快速版,简洁易上手 支持快速版和专业版切换使用,快速版界面简洁,保留主

如何免费的去使用connectedpapers?

免费使用connectedpapers 1. 打开谷歌浏览器2. 按住ctrl+shift+N,进入无痕模式3. 不需要登录(也就是访客模式)4. 两次用完,关闭无痕模式(继续重复步骤 2 - 4) 1. 打开谷歌浏览器 2. 按住ctrl+shift+N,进入无痕模式 输入网址:https://www.connectedpapers.com/ 3. 不需要登录(也就是