文章出处: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. 解析Qt中QThread使用方法

    本文讲述的是在Qt中QThread使用方法,QThread似乎是很难的一个东西,特别是信号和槽,有非常多的人(尽管使用者本人往往不知道)在用不恰当(甚至错误)的方式在使用QThread,随便用goog ...

  2. 关于Spring IOC容器解释

    何谓控制反转(IoC = Inversion of Control),何谓依赖注入(DI = Dependency Injection)?之前看到过两个比喻,觉得比较形象,特在此写下: IoC,用白话 ...

  3. 添加IFrame导致内存溢出的解决过程(IE浏览器,目前发现了原因,还未解决)

    1.  现象 每次动态添加iframe时,iexplore.exe进程占据的内存都会增加(大概10M左右),不会自动释放,最终导致内存溢出 2.  解决过程 经过网络的一番搜索,基本上给出的解决方案是 ...

  4. 在使用ICSharpCode.SharpZipLib进行目录压缩后,再解压缩是提示这个错误Size mismatch: 4294967295;126976 70202;126976

    在压缩代码中加入entry.CompressionMethod = CompressionMethod.Stored

  5. 1.7.6 Highlighting-高亮

    1 高亮 solr的高亮允许匹配用户查询的文档的片段包含在查询响应中返回,高亮包含在返回结果的单独部分(highlighting部分). solr提供了一个高亮工具的集合,这个工具允许控制大量字段的片 ...

  6. 1.6.1 什么是 Indexing

    这部分描述了建立索引的过程:添加内容到solr索引中,如果有需要,修改内容或者删除它.通过添加内容到索引里边,我们使其内容可以搜索. solr索引能够接收不同来源的数据,xml文件,逗号分隔值的(CV ...

  7. Linux 查看物理内存

    free -k free -m free -b man free cat /proc/meminfo

  8. 【Android 界面效果40】Android4.0-Fragment框架实现方式剖析(一)

    经过反复的学习对比,个人觉得带着问题学习新知是最有效的学习方式,因此文本就以提问的方式来讲述Fragment框架实现方式. 1.什么是Fragment? Fragment包含在Activity中,Fr ...

  9. cent os 6 安装 nginx

    cent os 6 默认的库是没有nginx的,所以直接 yum install nginx不行. 解决办法: $ wget http://nginx.org/packages/centos/6/no ...

  10. linux_cpu信息查询

    查看cpu信息: [root@css-management ~]# cat /proc/cpuinfo processor : 0vendor_id : GenuineIntelcpu family ...