文章出处:http://www.cnblogs.com/zplutor/

看到有一位同学在头文件中这么写:

 static const wchar_t* g_str1 = …
static const wchar_t* g_str2 = …

这种定义变量的方式我从来没有见过,而且它还能顺利通过编译,于是我很想知道编译器是如何处理这种变量定义的。

定义全局变量时使用static,意味着该变量的作用域只限于定义它的源文件中,其它源文件不能访问。既然这种定义方式出现在头文件中,那么可以很自然地推测:包含了该头文件的所有源文件中都定义了这些变量,即该头文件被包含了多少次,这些变量就定义了多少次。

假如将上面两行代码的static去掉,编译的时候就会出现变量重定义的错误,这进一步证实了上面的推测,因为没有static的话变量的作用域是全局的,定义了两个以上的同名变量就会出现该错误。

推测终究是推测,要真正证实这个推测还要通过写代码来验证。验证的方式是:在头文件中使用static定义变量,在多个源文件中包含该头文件,然后在每个源文件中输出变量的地址,同时在一个源文件中改变变量的值并输出,在另一个源文件中也输出。如果每个源文件的输出都不同,则推测得证;否则推测是错误的。

下面是定义变量的头文件的代码:

 //Header.h
#pragma once static int g_int = ;

接下来在另一个头文件中声明两个测试函数:

 //Functions.h
#pragma once void TestSource1();
void TestSource2();

分别在两个源文件中定义这两个测试函数:

 //Source1.cpp
#include <stdio.h>
#include "Header.h" void TestSource1() { wprintf(L"g_int's address in Source1.cpp: %08x\n", &g_int);
g_int = ;
wprintf(L"g_int's value in Source1.cpp: %d\n", g_int);
}
 //Source2.cpp
#include <stdio.h>
#include "Header.h" void TestSource2() { wprintf(L"g_int's address in Source2.cpp: %08x\n", &g_int);
wprintf(L"g_int's value in Source2.cpp: %d\n", g_int);
}

最后在main函数中调用这两个测试函数:

 //Main.cpp
#include "Functions.h" int wmain() { TestSource1();
TestSource2();
}

运行该程序:

可以看到,虽然在代码中好像使用了相同的变量,但是实际上使用的是不同的变量,在每个源文件中都有单独的变量。所以,在头文件中定义static变量会造成变量多次定义,造成内存空间的浪费,而且也不是真正的全局变量。应该避免使用这种定义方式。

作为对比,下面使用正确的方式来定义全局变量:

 //Header.h
#pragma once extern int g_int;
 //Source1.cpp
#include <stdio.h>
#include "Header.h" int g_int = ; void TestSource1() { wprintf(L"g_int's address in Source1.cpp: %08x\n", &g_int);
g_int = ;
wprintf(L"g_int's value in Source1.cpp: %d\n", g_int); }

其它文件不变。

运行程序:

可以看到,这次两个源文件中使用的都是同一个变量。要注意的是,使用extern声明变量时不能带有初始值,否则仍然属于变量定义,会出现变量重定义的错误。

[C/C++]在头文件中使用static定义变量意味着什么的更多相关文章

  1. C++-模板的声明和实现为何要放在头文件中

    源: http://blog.csdn.net/lqk1985/archive/2008/10/24/3136364.aspx 如何组织编写模板程序 发表日期: 1/21/2003 12:28:58 ...

  2. C ++模板的声明和实现为何要放在头文件中?

    源: http://blog.csdn.net/lqk1985/archive/2008/10/24/3136364.aspx 如何组织编写模板程序 发表日期: 1/21/2003 12:28:58 ...

  3. c语言头文件中定义全局变量的问题

    c语言头文件中定义全局变量的问题 (转http://www.cnblogs.com/Sorean/) 先说一下,全局变量只能定义在 函数里面,任意函数,其他函数在使用的时候用extern声明.千万不要 ...

  4. c++ inline使函数实现可以在头文件中,避免多重定义错误

    作者:Jon Lee链接:https://www.zhihu.com/question/53082910/answer/133612920来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业 ...

  5. cctype头文件中的一些内容

    1. string 标准库 1.1初始化 string s1; 默认构造函数s1为空 string s2(s1); 将s2初始化为s1的一个副本 string s3(“value”); 将s3初始化为 ...

  6. Effective Objective-C 2.0 — 第二条:类的头文件中尽量少引入其他头文件

    第二条:类的头文件中尽量少引入其他头文件 使用向前声明(forward declaring) @class EOCEmployer 1, 将引入头文件的实际尽量延后,只在确有需要时才引入,这样就可以减 ...

  7. 将inline、template声明和定义在头文件中

    如果要在要在源文件(a.cpp)中内联的展开一个函数(fun),则该源文件(a.cpp)中必须包含此函数(fun)的定义.如果要在多个文件中内联的展开fun,则在所有的源文件中都必须包含fun的定义. ...

  8. 头文件中的#ifndef/#define/#endif 的作用

    在一个大的软件工程里面,可能会有多个文件同时包含一个头文件,当这些文件编译链接成一个可执行文件时,就会出现大量重定义的错误.在头文件中实用#ifndef #define #endif能避免头文件的重定 ...

  9. C++头文件中预编译宏的目的

    C++头文件中预编译宏的目的 eg: #ifndef _FACTORY_H_#define _FACTORY_H_......#endif //~_FACTORY_H_ 防止头文件被重复包含,导致变量 ...

随机推荐

  1. sqoop1.99.4 JAVA API操作

    貌似天国还没有介绍1.99.4的java操作代码的,自己吃一次螃蟹吧 如果你是MAVEN项目 <dependency> <groupId>org.apache.sqoop< ...

  2. IIS 之 HTTP 错误 500.19(无法访问请求页面,因为该页的相关配置数据无效)

    HTTP 错误 500.19- Internal Server Error 错误解决方法,碰到这个问题的原因有很多,大家可以参考下,看属于哪种情况. 刚在本机部署了一个WebService测试,浏览的 ...

  3. 使用SourceTree

    SourceTree是个git的GUI软件. 教程将“使用Git”那个小节可视化,更为直观. 第一次启动的时候选择忽略,然后直接进入界面.  填入git地址与注册邮箱即可 例如mindset这本书的g ...

  4. 《算法导论》习题解答 Chapter 22.1-2(邻接矩阵与链表)

    链表如图: 矩阵: 1 2 3 4 5 6 7 1 0 1 1 0 0 0 0 2 1 0 0 1 1 0 0 3 1 0 0 0 0 1 1 4 0 1 0 0 0 0 0 5 0 1 0 0 0 ...

  5. tornado 信号处理

    一般情况下,对于线上的程序,我们是不能采取kill -9 来杀掉进程的 因为程序可能有未处理完的程序,如果贸然采取kill -9可能会导致数据不一致 如果需要关闭程序怎么办呢,一般情况下我们采取信号技 ...

  6. 代码研磨 Slim v3 (二)--app->run()

    APP->run()代码如下:   /** * Run application * * This method traverses the application middleware stac ...

  7. Android处理Bitmap使其能够不失真等比缩放裁剪后显示在ImageView上

    Android开发过程中,我们有时需要动态得显示一些图片,并且这些图片的大小差距会十分大,如果需求并不是需要图片完整显示,但是需要不失真,并且要图片中间部分的情况下,我们需要做一系列处理,因为这个时候 ...

  8. wamp图标黄色的另一种可能原因

    学习php用的是wamp即windows+apache+mysql+php,但是当启动的时候,图标为黄色(正常应为绿色),开始以为是端口的问题,但是将端口改掉依旧如此,后来发现是机器装的sqlserv ...

  9. jQuery简单邮箱验证

    function chekmail() { var szReg = /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/; ...

  10. 将ubuntu14.04设置为文本模式启动?

    修改改GRUB 的配置文件(不建议直接改 grub.conf) $sudo vim /etc/default/grub 找到: GRUB_CMDLINE_LINUX_DEFAULT="qui ...