宏的使用 extern
声明全局变量使用的技术。
有些时候C语言的一些条条框框就像语法。学会C语言就是学会了语法。
但是语法怎样使用就又是另一回事了。
我希望自己能多学习一些技巧,而不是一些固定的C语言语法。
这篇文章真的很好:参考:http://blog.chinaunix.net/uid-2282111-id-2113225.html
是关于如何定义全局变量的。
之前在我没有看μC/OS的时候,写过时间片轮转的程序。
那个时候定义全局变量真的很痛苦,总是报错说某某文件已经定义了。
后来才知道,可以在oled.c里面定义一个变量cnt.
如果你想让主函数,或者其他的文件(如key.c)也用到这个cnt,
就需要在oled.h文件中加入extern int cnt
这样就可以在main.c或者key.c中定义#include"oled.h" ,就可以在main.c或key.c中调用cnt变量了.
但是这里讲的是另一种方法:
以下是如何定义全局 变量。众所周知,全局变量应该是得到内存分配且可以被其他模块通过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
#i nclude "includes.h"
当
编译器处理.C
文件时,它强制xxx_EXT(在相应.H文件中可以找到)为空,(因为xxx_GLOBALS已经定义)。所以编译器给每个全局变量分配内存空间,而当
编译器处理其他.C 文件时,xxx_GLOBAL 没有定义,xxx_EXT
被定义为extern,这样用户就可以调用外部全局变量。为了说明这个概念,可以参见uC/OS_II.H,其中包括以下定义:
#ifdef OS_GLOBALS
#define OS_EXT //这句话可以理解为把 OS_EXT定义成 ' ' ,也就是定义成空格的意思.
#else
#define OS_EXT extern
#endif
OS_EXT INT32U OSIdleCtr;
OS_EXT INT32U OSIdleCtrRun;
OS_EXT INT32U OSIdleCtrMax;
同时,uCOS_II.H 有中以下定义:
#define OS_GLOBALS
#i nclude “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的更多相关文章
- 理解宏的使用 extern
如何定义一个全局变量在一个文件中,然后在其它文件中调用就行,而不需要多次extern外部声明. 由于之前的公司的程序中全局的变量使用得很多,在多个.C文件中会调用,不这样处理做的话就会多处进行exte ...
- VC分发包版本问题
来源:http://www.cnblogs.com/mixiyou/archive/2010/02/09/1663620.html 之前曾经写过一篇个人经历,是关于VC2005分发包版本不一致而引起应 ...
- 使用DLL进行不同语言之间的调用(转)
源:使用DLL进行不同语言之间的调用 __declspec(dllexport) 是告诉编译器用来导出函数的,在代码中不另作说明了. extern "C" 的意思就是用C的方式来导 ...
- 如何使用 VS生成动态库?
如何使用 VS生成动态库? //.cpp 文件默认定义了 __cplusplus 宏 #ifdef __cplusplus extern "C"{ #endif xxx #ifde ...
- #if defined(__cplusplus)
由于C++编译器需要支持函数的重载,会改变函数的名称,因此dll的导出函数通常是标准C定义的.这就使得C和C++的互相调用变得很常见.但是有时可能又会直接用C来调用,不想重新写代码,让标准C编写的dl ...
- C与C++混编
了解一下C与C++如何合作,gcc和g++编译出来的东西有什么区别. 工具使用 objdump是个好工具,可以用于查看.o文件的内容,也可以查看可执行文件的内容. 查看符号表 objdump -t f ...
- C 标准库 - <errno.h>
C 标准库 - <errno.h> 简介 C 标准库的 errno.h 头文件定义了整数变量 errno,它是通过系统调用设置的,在错误事件中的某些库函数表明了什么发生了错误.该宏扩展为类 ...
- 【VS开发】MFC中调用C函数模块的解决方案
[VS开发]MFC中调用C函数模块的解决方案 标签(空格分隔): [VS开发] 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 说明:最近调试基于MFC的程序 ...
- C++关键字总结【新手必学】
const 关键字——常量const 与definedefine是预编译器的编译指令,它从C语言兼容下来,工作方式与文本编辑器中的全局搜索和替换相似.define定义的常量的意义在它开始的地方持续到文 ...
随机推荐
- 今日SGU 5.15
最近事情好多,数据库作业,没天要学2个小时java,所以更新的sgu就比较少了 SGU 131 题意:给你两种小块一种,1*1,一种2*2-1*1,问你填满一个m*n的矩形有多少钟方法,n和m小于等于 ...
- 36Kr众筹项目比呀比biyabi,调查分析研究报告,背后资方势力的关系梳理
36Kr众筹项目比呀比biyabi调查报告 个层次的评价. 变革家-比呀比拆解报告:http://biangejia.com/archives/12653 8.其它 没有通过微信,参加路演,有点遗 ...
- Vue2.0八——知识点整理
1.active-class是哪个组件的属性?嵌套路由怎么定义? 答:vue-router模块的router-link组件. 2.怎么定义vue-router的动态路由?怎么获取传过来的动态参数? 答 ...
- 【CS Round #37 (Div. 2 only) B】Group Split
[Link]:https://csacademy.com/contest/round-37/task/group-split/ [Description] 让你把一个数分成两个数a.b的和; (a,b ...
- Silverlight 应用程序中未处理的错误
Silverlight 开发中遇到个错误: SCRIPT5022: Silverlight 应用程序中未处理的错误 代码: 2108 类别: InitializeError 消息: 无法下载初始屏幕或 ...
- PostgreSQL递归查询实现树状结构查询
在Postgresql的使用过程中发现了一个非常有意思的功能,就是对于须要相似于树状结构的结果能够使用递归查询实现.比方说我们经常使用的公司部门这样的数据结构.一般我们设计表结构的时候都是相似以下的S ...
- Linux经常使用命令(十六) - whereis
whereis命令仅仅能用于程序名的搜索(程序安装在哪?).并且仅仅搜索二进制文件(參数-b).man说明文件(參数-m)和源码文件(參数-s). 假设省略參数,则返回全部信息. 和find相比.wh ...
- Thinkphp5图片上传正常,音频和视频上传失败的原因及解决
Thinkphp5图片上传正常,音频和视频上传失败的原因及解决 一.总结 一句话总结:php中默认限制了上传文件的大小为2M,查找错误的时候百度,且根据错误提示来查找错误. 我的实际问题是: 我的表单 ...
- POJ 2394 Dijkstra
题意: 思路: 裸的Dijkstra 爆敲一发模板 //By SiriusRen #include <queue> #include <cstdio> #include < ...
- Kinect 开发 —— 深度信息
转自:http://www.cnblogs.com/yangecnu/archive/2012/04/04/KinectSDK_Depth_Image_Processing_Part1.html 深度 ...