在头文件声明全局变量和创建extern

问题:

是否有简单的方法,在头文件里定义我的变量,同时也为它们创建extern定义?

回答:

是的。尽管这不是必需的,使用正确的宏和一个头文件还是很容易实现的。

通常,你在C文件中声明一个变量,而在头文件中创建extern定义。然而,如果你想的话,下面的技巧用来在同一个头文件中声明变量,并且对它们进行extern定义。

首先,创建一个头文件如下(如vars.h):

/*----------------------------------------------------------------------------
vars.h
注:在包含vars.h头文件声明和初始化全局变量前面使用 #define VAR_DECLS 1语句。
只是包含它,而不定义VAR_DECLS以引用变量。
----------------------------------------------------------------------------*/
#ifndef VAR_DEFS // 保证文件只被包含一次
#define VAR_DEFS 1
/*----------------------------------------------
设置变量声明宏
----------------------------------------------*/
#ifndef VAR_DECLS
# define _DECL extern
# define _INIT(x)
#else
# define _DECL
# define _INIT(x) = x
#endif
/*----------------------------------------------
声明变量如下:
_DECL [标准变量声明] _INIT(x);
x是初始化变量的值。如果变量没有初始化的值,可以如下声明
_DECL [标准变量声明];
----------------------------------------------*/
_DECL int var_a _INIT(100);
_DECL int var_b;
_DECL int var_c _INIT(27);
#endif
/*----------------------------------------------------------------------------
----------------------------------------------------------------------------*/

vars.h声明了3个全局变量:

int var_a = 100;

int var_b;

int var_c = 27;


第2,在同一个源文件,在包含vars.h前面包含下列 #define:

#define VAR_DECLS
#include "vars.h"

#define VAR_DECLS 引发vars.h包含文件实际声明并初始化全局变量。

最后,在所有其他源文件(使用这些变量)中简单包含vars.h头文件:

#include "vars.h"

保证VAR_DECLS 在其他文件中不被定义,否则你的变量会被声明2次。

来源于国内uC/OS-II 2.0  Word文档的描述(吕进华):

全局变量

以下是如何定义全局变量。众所周知,全局变量应该是得到内存分配且可以被其他模块通过C语言中extern关键字调用的变量。因此,必须在 .C 和 .H 文件中定义。这种重复的定义很容易导致错误。以下讨论的方法只需用在头文件中定义一次。虽然有点不易懂,但用户一旦掌握,使用起来却很灵活。表1.2中的定义出现在定义所有全局变量的.H头文件中。

程序清单 L 1.2  定义全局宏。

#ifdef   xxx_GLOBALS

#define  xxx_EXT

#else

#define  xxx_EXT extern

#endif

.H 文件中每个全局变量都加上了xxx_EXT的前缀。xxx代表模块的名字。该模块的.C文件中有以下定义:

#define  xxx_GLOBALS

#include "includes.h"
 

当编译器处理.C文件时,它强制xxx_EXT(在相应.H文件中可以找到)为空,(因为xxx_GLOBALS已经定义)。所以编译器给每个全局变量分配内存空间,而当编译器处理其他.C文件时,xxx_GLOBAL没有定义,xxx_EXT被定义为extern,这样用户就可以调用外部全局变量。为了说明这个概念,可以参见uC/OS_II.H,其中包括以下定义:

#ifdef   OS_GLOBALS             //第22行

#define  OS_EXT

#else

#define  OS_EXT extern

#endif

OS_EXT  INT32U       OSIdleCtr;

OS_EXT  INT32U       OSIdleCtrRun;

OS_EXT  INT32U       OSIdleCtrMax;
 

同时,uCOS_II.C有中以下定义:

#define  OS_GLOBALS

#include “includes.h”

当编译器处理uCOS_II.C时,它使得头文件变成如下所示,因为OS_EXT被设置为空。

INT32U       OSIdleCtr;

INT32U       OSIdleCtrRun;

INT32U       OSIdleCtrMax;

这样编译器就会将这些全局变量分配在内存中。当编译器处理其他.C文件时,头文件变成了如下的样子,因为OS_GLOBAL没有定义,所以OS_EXT被定义为extern。

extern INT32U       OSIdleCtr;

extern INT32U       OSIdleCtrRun;

extern INT32U       OSIdleCtrMax;

在这种情况下,不产生内存分配,而任何 .C文件都可以使用这些变量。这样的就只需在 .H 文件中定义一次就可以了。

在头文件声明全局变量和创建extern的更多相关文章

  1. 多文件 定义全局变量的使用 extern

    extern 申明变量在其他文件中定义了.如果变量放在*.h头文件,其它cpp文件加载*.h头文件就会出现变量定义重复. 头文件 DHeah.h #include <iostream> u ...

  2. [C语言]防止头文件和全局变量重复定义

      昨天下午将全局变量定义在H文件中导致链接时提示变量在多个obj文件内重复. 解决办法如下: 将变量移入C文件中进行定义,然后在H文件中加入extern在变量之前. 这样当其它C文件引用该全局变量时 ...

  3. C预编译, 预处理, C/C++头文件, 编译控制,

    在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作.#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的 ...

  4. C++中头文件(.h)和源文件(.cpp)都应该写些什么

    头文件(.h): 写类的声明(包括类里面的成员和方法的声明).函数原型.#define常数等,但一般来说不写出具体的实现. 在写头文件时需要注意,在开头和结尾处必须按照如下样式加上预编译语句(如下): ...

  5. C++的头文件和实现文件分别写什么

    在C++编程过程中,随着项目的越来越大,代码也会越来越多,并且难以管理和分析.于是,在C++中就要分出了头(.h)文件和实现(.cpp)文件,并且也有了Package的概念. 对于以C起步,C#作为& ...

  6. C语言头文件的作用

    C99中规定, 所有顶层的默认存储类标志符都是extern ! 头文件中声明的函数,默认都是extern前缀.但是为了我们程序员方便,我们采取下面的手段: 我个人认为是extern催生了头文件的诞生. ...

  7. linux 编译指定库、头文件的路径问题(转)

    1. 为什么会出现undefined reference to 'xxxxx'错误? 首先这是链接错误,不是编译错误,也就是说如果只有这个错误,说明你的程序源码本身没有问题,是你用编译器编译时参数用得 ...

  8. C++自学笔记 头文件 (header file)关于 #include 和.h

    头文件 在C++中定义Definition一个类的时候 要用分别的.h和.cpp文件去定义这个类 .h和.cpp成对出现 类的声明declaration和函数原型放在头文件里(.h) 定义这些函数的结 ...

  9. C++ 包含头文件 和 宏的使用 和 条件编译

    1 #define命令剖析 1.1   #define的概念     #define命令是C语言中的一个宏定义命令,它用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本. ...

随机推荐

  1. 在IE6/7下表格td标签没有内容时不显示边框?

    有以下几种方法: 1.在单元格中加入一个空格.这样: <td> </td> 2.直接在table里这样写:<table border="0" cell ...

  2. cad实时平移快捷键

    1.按住鼠标滚轮,光标变成小手工具,可拖动画布 2.键盘按 p,光标变成小手工具

  3. 在cad中画一条长500mm,垂直90度的线段

    视频教程奉上 方法1.点击线段按钮,鼠标指定一点,输入500,再输入<90. 方法2,点击线段按钮,鼠标指定一点,输入500,按tab,再输入90.

  4. 製程能力介紹(SPC introduction) ─ 製程能力改善及評估

    如何改善製程能力 參考下面常態分配圖,原製程能力不足,其製成品有一定比率超出下限規格,其改善對策有二: 縮小製程變異,也就是改善Cp,提高Cp的值. 移動製程中心,也就是改善Ck,減小Ck的值. 就技 ...

  5. RDIFramework.NET(.NET快速信息化系统开发框架) Web版介绍

    RDIFramework.NET(.NET快速信息化系统开发框架)  Web版介绍 B/S结构(Browser/Server,浏览器/服务器模式),是WEB兴起后的一种网络结构模式,WEB浏览器是客户 ...

  6. Cocos2d-x 3.1.1 学习日志6--30分钟了解C++11新特性

    新的keyword auto C++11中引入auto第一种作用是为了自己主动类型推导 auto的自己主动类型推导,用于从初始化表达式中判断出变量的数据类型.通过auto的自己主动类型推导.能够大大简 ...

  7. phpExcel在封装

    <?php /** * 数组生成Excel * @author zouhao zouhao619@gmail.com * 使用示例 * $excel =new Excel(); $data=ar ...

  8. PPT插件 用js制作PPT

    https://github.com/bartaz/impress.js/ deck.js

  9. web前端学习之路

    test 随着自己对于web前端知识了解的越多,越来越发现自己真的好菜 一脸茫然阶段 两年前大学接触网页设计,那时对于网页设计一窍不通,只是看了一本自己大学编的一本入门教材,我甚至不知道那些网页设计的 ...

  10. 一键搞定Java桌面应用安装部署 —— exe4j + Inno Setup 带着JRE, 8M起飞

    转载自:http://www.blogjava.net/huliqing/archive/2008/04/18/193907.html 对于作Java桌面应用来说,比较烦人的就是安装部署问题,客户端是 ...