#define #include #undef的其中一个用法(目的)
一、背景
最近在跟一段系统级的代码,和原来单纯的下位机代码相比,真的是刘姥姥进大观园——看花了眼。相较于
之前所常见的各种下位机代码,系统级代码常常会出现深层次结构体嵌套,结构体内的各种回调函数导致对函数
指针的赋值调用也成为常态,以及各种各样的宏定义等等,均让人有一种眼前一亮、耳目一新的既视感。由于
对宏了解不多,也就对此处我在实际代码碰到过的#define,#include,#undef的使用的其中一个目的做个
记录。
二、正文
实际代码如下: #define _MCARO_1
#include "Myheadfile.h"
#undef _MACRO_1
紧接着的代码:
#define _MCARO_2
#include "Myheadfile.h"
#undef _MACRO_2 出现这段代码的作用即重复包含了两次头文件"Myheadfile.h",可意义在哪?接着跟头文件内的代码,
该头文件的作用是声明定义了一张类似于表格的变量,表格即是通过定义普通数组或者结构体数组来实现。而在
该头文件内出现了如下宏: #if defined (_MCARO_1)
···
对表格实际的各个变量的声明;
···
#elif defined (_MACRO_2)
···
对表格实际的各个变量的声明;
··· 从代码上来分析,重复包含两次头文件的意义就在于根据宏定义的不同来申请两种不同的变量。
以我碰到的实际代码来说,该工程实际上是要实现一个CANopen设备,CANopen设备通过对象字典来描述其功
能,以及通过对象字典来与外界交互,对象字典代码上实现就相当于一个表格,(关于CANopen对象字典以后会另外
开篇博客详述),在CANopen设备初始化的时候,CANopen设备会通过默认的对象字典来实现其预定义的功能,但在
CANopen设备实际运行起来时,又会按照不同的工业现场情况被CANopen主设备配置成适应当时需求的从设备,对象
字典内的参数也因此会被更改,但该设备被应用到其他场合时,它还是应该以默认的CANopen设备进行初始化。
上述代码既是实现了这种需求:
当其"define_MACRO_1"时,在该头文件内声明的变量空间为CANopen默认的对象字典参数。
当其"define_MACRO_2"时,在该头文件内声明的变量空间为CANopen实际运行的可被更改的对象字典参数。
两个对象字典参数并存于同一段代码中,而互不干涉。
因此,综上所述,#define,#include,#undef 在使用时,会在被包含的头文件内按照定义的宏进行特定的
操作,而同时再被包含时,由于宏的不同,其不会出现再次重复定义的错误。 再补充一个带参宏的用法: #define Test(par) Function(par);
void Function(int par);
int main(void) {
Test(par);
//中间若是加空格也可以调用Function(par);
Test (par);
}
也即是说,定义带参数的宏,在定义时,宏与参数之间不得有空格,但在调用时,则可以有空格。 至此,记录完毕。 记录时间:--
记录地点:深圳WZ
#define #include #undef的其中一个用法(目的)的更多相关文章
- block extends include三者的差别跟用法
block extends include三者的差别跟用法 一.定义基础模板,在html内容中定义多个block块,block由子模板引用同名block块,来决定是否替换这些部分{% block ti ...
- #define、#undef、#ifdef、#ifndef、#if、#elif、#else、#endif、defined解释
#define.#undef.#ifdef.#ifndef.#if.#elif.#else.#endif.defined. #define 定义一个预处理宏#undef ...
- #include #import @class 的一些用法区别
从网上查了一些资料,整理了一下,发现很多都说的比较详尽,下面摘录自网络 说一下#import同class之间的区别 在ios中我们经常会在.h和.m中引入一些类啊等等一般用的是#import来进行声明 ...
- #define,#undef宏学习
1.预处理器 1.1预处理符号: __FILE__ :进行编译的源文件名字 __LINE__ :文件当前行的行号 __DATA__ :文件被编译的日期 __TIME__ :文件被编译的时间 __STD ...
- ThinkPHP第十天(_initialize方法,SESSION销毁,分组配置,include文件引入,JOIN用法)
1.Action类中的_initialize()函数,先于任何自定义操作函数运行,可认为是控制器的前置操作.可用于检测用户是否登录等检测. 如果多个模块(Action)需要相同_initialize( ...
- Android——ViewGroup的一个用法实例(转载)
找了很久,终于找到了. <?xml version="1.0" encoding="UTF-8" ?> <merge xmlns:androi ...
- 09_Android中ContentProvider和Sqllite混合操作,一个项目调用另外一个项目的ContentProvider
1. 编写ContentPrivider提供者的Android应用 清单文件 <?xml version="1.0" encoding="utf-8"? ...
- 常用代码之五:RequireJS, 一个Define需要且只能有一个返回值/对象,一个JS文件里只能放一个Define.
RequireJS 介绍说一个JS文件里只能放一个Define,这个众所周知,不提. 关于Define,它需要有一个返回值/对象,且只能有一个返回值/对象,这一点却是好多帖子没有提到的,但又非常重要的 ...
- 一个项目的Makefile编写及调试
父Makefile 在src目录下包含很多文件夹,那么需要遍历所有的目录执行Makefile,那么给一个在src目录下的Makefile. # 需要排除的目录 exclude_dirs := incl ...
随机推荐
- Comparison of SQL Server Compact, SQLite, SQL Server Express and LocalDB
Information about LocalDB comes from here and SQL Server 2014 Books Online. LocalDB is the full SQL ...
- 《javascript》高级程序设计——类型转换错误
容易发生类型转换错误的另一个地方,就是流控制语句.像if之类的语句在确定下一步操作之前,会自动把任何值转换成布尔值.尤其是if语句,如果使用不当,最容易出错.来看下面的例子. function con ...
- [转]NET Core中实现一个Token base的身份认证
本文转自:http://www.cnblogs.com/Leo_wl/p/6077203.html 注:本文提到的代码示例下载地址> How to achieve a bearer token ...
- Vector3.forward
这里我要说的就是Vector3.forward ,它等价与 new Vector3(0,0,1):它并不是一个坐标,它是一个标准向量,方向是沿着Z轴向前.这样平移一次的距离就是1米, 如果 Vecto ...
- tagfield
- Centos7 防火墙简介(一)
Centos7下的防火墙默认是通过一个守护进程(firewalld)为网络(network) 以及与之相关的连接(connections)和接口(interface)提供一个可信层,同时支持网络空间( ...
- 学习C++.Primer.Plus 10 对象和类
1.类的声明和定义 类的声明和定义. 类声明的格式如下: class className { private://private 是类对象的默认访问控制,因此,可以省略 data member del ...
- 最新版CentOS6.5上安装部署ASP.NET MVC4和WebApi
最新版CentOS6.5上安装部署ASP.NET MVC4和WebApi 使用Jexus5.8.1独立版 http://www.linuxdot.net/ ps:该“独立版”支持64位的CentOS ...
- web前端
设置透明: filter: alpha(opacity=70); opacity: 0.7; 设置文字与文字之间的间隙 letter-spacing: 5px; 设置单词与单词之间的间隙 word-s ...
- 基于Calabash-andriod的UI自动化测试(1)-环境和原理
有时候,一些覆盖happy path的UI自动化还是很有用的.它的一些作用如下: 1.可以迅速实现端到端的功能回归,能够覆盖接口测试覆盖不到的一些地方,如GUI层和接口层的交互产生的问题. 2.非码农 ...