C语言宏定义技巧
C语言宏定义技巧(常用宏定义)
写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性等等。下面列举一些成熟软件中常用得宏定义。
1、防止一个头文件被重复包含
#ifndef COMDEF_H
#define COMDEF_H
//头文件内容
#endif
2、重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。
typedef unsigned char boolean; /* Boolean value type. */
typedef unsigned long int uint32; /* Unsigned 32 bit value */
typedef unsigned short uint16; /* Unsigned 16 bit value */
typedef unsigned char uint8; /* Unsigned 8 bit value */
typedef signed long int int32; /* Signed 32 bit value */
typedef signed short int16; /* Signed 16 bit value */
typedef signed char int8; /* Signed 8 bit value */
//下面的不建议使用
typedef unsigned char byte; /* Unsigned 8 bit value type. */
typedef unsigned short word; /* Unsinged 16 bit value type. */
typedef unsigned long dword; /* Unsigned 32 bit value type. */
typedef unsigned char uint1; /* Unsigned 8 bit value type. */
typedef unsigned short uint2; /* Unsigned 16 bit value type. */
typedef unsigned long uint4; /* Unsigned 32 bit value type. */
typedef signed char int1; /* Signed 8 bit value type. */
typedef signed short int2; /* Signed 16 bit value type. */
typedef long int int4; /* Signed 32 bit value type. */
typedef signed long sint31; /* Signed 32 bit value */
typedef signed short sint15; /* Signed 16 bit value */
typedef signed char sint7; /* Signed 8 bit value */
3、得到指定地址上的一个字节或字
#define MEM_B( x ) ( *( (byte *) (x) ) )
#define MEM_W( x ) ( *( (word *) (x) ) )
4、求最大值和最小值
#define MAX( x, y ) ( ((x) > (y)) ? (x) : (y) )
#define MIN( x, y ) ( ((x) < (y)) ? (x) : (y) )
5、得到一个field在结构体(struct)中的偏移量
#define FPOS( type, field ) \
/*lint -e545 */ ( (dword) &(( type *) 0)-> field ) /*lint +e545 */
6、得到一个结构体中field所占用的字节数
#define FSIZ( type, field ) sizeof( ((type *) 0)->field )
7、按照LSB格式把两个字节转化为一个Word
#define FLIPW( ray ) ( (((word) (ray)[0]) * 256) + (ray)[1] )
8、按照LSB格式把一个Word转化为两个字节
#define FLOPW( ray, val ) \
(ray)[0] = ((val) / 256); \
(ray)[1] = ((val) & 0xFF)
9、得到一个变量的地址(word宽度)
#define B_PTR( var ) ( (byte *) (void *) &(var) )
#define W_PTR( var ) ( (word *) (void *) &(var) )
10、得到一个字的高位和低位字节
#define WORD_LO(xxx) ((byte) ((word)(xxx) & 255))
#define WORD_HI(xxx) ((byte) ((word)(xxx) >> 8))
11、返回一个比X大的最接近的8的倍数
#define RND8( x ) ((((x) + 7) / 8 ) * 8 )
12、将一个字母转换为大写
#define UPCASE( c ) ( ((c) >= 'a' && (c) <= 'z') ? ((c) - 0x20) : (c) )
13、判断字符是不是10进值的数字
#define DECCHK( c ) ((c) >= '0' && (c) <= '9')
14、判断字符是不是16进值的数字
#define HEXCHK( c ) ( ((c) >= '0' && (c) <= '9') ||\
((c) >= 'A' && (c) <= 'F') ||\
((c) >= 'a' && (c) <= 'f') )
15、防止溢出的一个方法
#define INC_SAT( val ) (val = ((val)+1 > (val)) ? (val)+1 : (val))
16、返回数组元素的个数
#define ARR_SIZE( a ) ( sizeof( (a) ) / sizeof( (a[0]) ) )
17、返回一个无符号数n尾的值MOD_BY_POWER_OF_TWO(X,n)=X%(2^n)
#define MOD_BY_POWER_OF_TWO( val, mod_by ) \
( (dword)(val) & (dword)((mod_by)-1) )
18、对于IO空间映射在存储空间的结构,输入输出处理
#define inp(port) (*((volatile byte *) (port)))
#define inpw(port) (*((volatile word *) (port)))
#define inpdw(port) (*((volatile dword *)(port)))
#define outp(port, val) (*((volatile byte *) (port)) = ((byte) (val)))
#define outpw(port, val) (*((volatile word *) (port)) = ((word) (val)))
#define outpdw(port, val) (*((volatile dword *) (port)) = ((dword) (val)))
19、使用一些宏跟踪调试,A N S I标准说明了五个预定义的宏名,它们是:
l _LINE_
l _FILE_
l _DATE_
l _TIME_
l _STDC_
如果编译不是标准的,则可能仅支持以上宏名中的几个,或根本不支持。记住编译程序
也许还提供其它预定义的宏名。
_ LINE _及_ FILE _宏指令在有关# line的部分中已讨论,这里讨论其余的宏名。
_ DATE _宏指令含有形式为月/日/年的串,表示源文件被翻译到代码时的日期。源代码翻译到目标代码的时间作为串包含在_TIME_中。串形式为时:分:秒。如果实现是标准的,则宏_STDC_含有十进制常量1。如果它含有任何其它数,则实现是非标准的。
可以定义宏,例如:
当定义了_DEBUG,输出数据信息和所在文件所在行
#ifdef _DEBUG
#define DEBUGMSG(msg,date) printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)
#else
#define DEBUGMSG(msg,date)
#endif
20、宏定义防止使用是错误
用小括号包含。
例如:#define ADD(a,b) (a+b)
用do{}while(0)语句包含多语句防止错误
例如:#difne DO(a,b) a+b;\
a++;
应用时:if(….)
DO(a,b); //产生错误
else
解决方法: #difne DO(a,b) do{a+b;\
a++;}while(0)
宏中"#"和"##"的用法
一、一般用法
我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起.
用法:
#i nclude<cstdio>
#i nclude<climits>
using namespace std;
#define STR(s) #s
#define CONS(a,b) int(a##e##b)
int main()
{
printf(STR(vck)); // 输出字符串"vck"
printf("%d\n", CONS(2,3)); // 2e3 输出:2000
return 0;
}
二、当宏参数是另一个宏的时候
需要注意的是凡宏定义里有用'#'或'##'的地方宏参数是不会再展开.
1、非'#'和'##'的情况
#define TOW (2)
#define MUL(a,b) (a*b)
printf("%d*%d=%d\n", TOW, TOW, MUL(TOW,TOW));
这行的宏会被展开为:
printf("%d*%d=%d\n", (2), (2), ((2)*(2)));
MUL里的参数TOW会被展开为(2).
2、当有'#'或'##'的时候
#define A (2)
#define STR(s) #s
#define CONS(a,b) int(a##e##b)
printf("int max: %s\n", STR(INT_MAX)); // INT_MAX #i nclude<climits>
这行会被展开为:
printf("int max: %s\n", "INT_MAX");
printf("%s\n", CONS(A, A)); // compile error
这一行则是:
printf("%s\n", int(AeA));
INT_MAX和A都不会再被展开, 然而解决这个问题的方法很简单. 加多一层中间转换宏.
加这层宏的用意是把所有宏的参数在这层里全部展开, 那么在转换宏里的那一个宏(_STR)就能得到正确的宏参数.
#define A (2)
#define _STR(s) #s
#define STR(s) _STR(s) // 转换宏
#define _CONS(a,b) int(a##e##b)
#define CONS(a,b) _CONS(a,b) // 转换宏
printf("int max: %s\n", STR(INT_MAX)); // INT_MAX,int型的最大值,为一个变量#i nclude<climits>
输出为: int max: 0x7fffffff
STR(INT_MAX) --> _STR(0x7fffffff) 然后再转换成字符串;
printf("%d\n", CONS(A, A));
输出为:200
CONS(A, A) --> _CONS((2), (2)) --> int((2)e(2))
三、'#'和'##'的一些应用特例
1、合并匿名变量名
#define ___ANONYMOUS1(type, var, line) type var##line
#define __ANONYMOUS0(type, line) ___ANONYMOUS1(type, _anonymous, line)
#define ANONYMOUS(type) __ANONYMOUS0(type, __LINE__)
例:ANONYMOUS(static int); 即: static int _anonymous70; 70表示该行行号;
第一层:ANONYMOUS(static int); --> __ANONYMOUS0(static int, __LINE__);
第二层: --> ___ANONYMOUS1(static int, _anonymous, 70);
第三层: --> static int _anonymous70;
即每次只能解开当前层的宏,所以__LINE__在第二层才能被解开;
2、填充结构
#define FILL(a) {a, #a}
enum IDD{OPEN, CLOSE};
typedef struct MSG{
IDD id;
const char * msg;
}MSG;
MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};
相当于:
MSG _msg[] = {{OPEN, "OPEN"},
{CLOSE, "CLOSE"}};
3、记录文件名
#define _GET_FILE_NAME(f) #f
#define GET_FILE_NAME(f) _GET_FILE_NAME(f)
static char FILE_NAME[] = GET_FILE_NAME(__FILE__);
4、得到一个数值类型所对应的字符串缓冲大小
#define _TYPE_BUF_SIZE(type) sizeof #type
#define TYPE_BUF_SIZE(type) _TYPE_BUF_SIZE(type)
char buf[TYPE_BUF_SIZE(INT_MAX)];
--> char buf[_TYPE_BUF_SIZE(0x7fffffff)];
--> char buf[sizeof "0x7fffffff"];
这里相当于:
char buf[11];
相关文章:

了解C++默默编写并调用哪些函数
在C中,如果你写下 1 classEmpty{…}; 就相当于写下1 classEmpty{ 2 public: 3 Empty();//default构造函数 4 Empty(constEmpty& rhs){……};//copy构造函数 5 ~Empty(){…}//析构函数 6 Empty&operator(constEmpty& rhs){…};//copy赋值运算符 7 }; 惟有…
仅50张图片训练数据的AI分类技术PK,阿里拿下ECCV 2020竞赛冠军
出品 | AI科技大本营(ID:rgznai100)近日,两年一度的世界计算机视觉领域顶会ECCV 2020的各项挑战赛结果出炉,在图像分类赛中,阿里安全的高效AI分类技术超越三星、深兰科技、同济大学等国内外多支队伍的同类技术获得冠军…

Eclipse生成jar文件
2019独角兽企业重金招聘Python工程师标准>>> 具体做法如下: 方法一:(工程没有引用外部jar包时,直接导出) 选中工程---->右键,Export...--->Java--->JAR file--->next-->选择jar file的路径及名称-->…

动态的管理ASP.NET DataGrid数据列
动网先锋 在ASP.NET的DataGrid数据显示控件编程中,我们有几种方式可以增加DataGrid columns。其中最常见的方法是在web forms设计器中增加,通过在控件工具箱中拖访DataGrid控件到web设计页面,然后在属性生成器中增加Columns列;还有一种方式就…

Django模型层Meta内部类详解
Django 模型类的Meta是一个内部类,它用于定义一些Django模型类的行为特性。以下对此作一总结: abstract这个属性是定义当前的模型类是不是一个抽象类。所谓抽象类是不会对应数据库表的。一般我们用它来归纳一些公共属性字段,然后继承它的子类…

ASP.NET虚拟主机的重大安全隐患
作者:秦海鹏 来自: yesky 说明:本文中所有程序均在Windows 2000 Server中文版 SP2上编译运行无误开发环境:.Net 框架1.0 Version 1.0.3705 一、ASP.NET虚拟主机存在的重大隐患 我曾经在WWW.BRINKSTER.COM申请了一个免费的…
给力!一行代码躺赚普通程序员10年薪资!
笔者这两天闲逛知乎,看到了这个帖子:匿名答题,发表于2014年,此外没有留下任何多余信息。2年躺赚200万,相当于普通程序员10年的工资。没想到Pyhon这么强大,怪不得有人说“除了不会生孩子,Python什…

Hello world!
2019独角兽企业重金招聘Python工程师标准>>> 向世界打招呼,大家好,这是我的第一篇文章,我准备在这里开博! 转载于:https://my.oschina.net/chinesedragon/blog/57259

在VMware Workstation上安装Ubuntu 16.04 Server操作系统
Ubuntu 16.04 Server的下载 http://www.ubuntu.org.cn/download/server 按空格键(Space)选中第一个ssh服务 成功!

ASP.NET中WebForm组件CheckBoxList编程
作者:马金虎 来自:yesky CheckBox选择组件是一个程序中都经常的组件。在程序设计中使用到该组件,一般都不会只使用到一个,往往是以多个此类组件的形式出现的。在ASP.NET页面中如果要使用到多个CheckBox组件,除了添加…
今晚 8 点直播 | OpenCV 20 年,首款开源软硬一体的 OAK 套件来了!
从 2000 年首个开源 OpenCV Alpha 版本,到不久前刚刚发布的 OpenCV 4.4,跨平台计算机视觉库 OpenCV 在不知不觉间已经走过了 20 个年头。相信不少 IT、AI 的从业者几乎都使用过。据 CSDN 发布的《中国AI应用开发者报告2020》显示,作为计算机视…

Linux常用压缩解压命令
1.tar基本用法:1.打包文件:tar -cvf ~/test.tar ~/test 2.打包并压缩文件:tar -zcvf ~/test.tar.gz ~/test2.解包文件:先切换到要解包到的目录,然后执行:tar -xvf ~/test.tar参数详解:-c, --cre…

第二课 , 启动 ./start-all.sh
2019独角兽企业重金招聘Python工程师标准>>> 一.安装环境 1.保持第一课的基础 2.关闭防火墙 ,node1,node2,node3 service iptables stop 3.修改conf/mapred-site.xml <configuration><property><name>mapred.job.tracker</name><value&…

ASP.NET的WebFrom组件LinkButton编程
作者:阿虎 来自:yesky 在ASP.NET的WebForm组件中的LinkButton组件也是一个服务器端的组件,这个组件有点类似于HTML中的<A>标识符。它的主要作用是就是在ASP.NET页面中显示一个超链接。当这个链接被按动的时候&#x…
Python再夺冠,上古语言COBOL大流行,IEEE Spectrum 2020年度编程语言排行榜出炉!...
整理 | 屠敏题图 | 东方 IC出品 | CSDN 博客领域驱动技术,技术鞭策领域。近日,IEEE Spectrum 最新发布了 2020 年年度编程语言排行榜。IEEE Spectrum 编程语言排行榜一年发布一次,截止到今年,该排行榜已经连续发布了七年。与其他榜…

NSStream线程阻塞处理
http://www.10bay.com/?p149 [[session inputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; 因主线程有事务要处理,会阻塞主线程外设事件的触发; 解决: “将socket的runloopsource添加到新开的…

Python笔记
精简,快速,并持续完善。输入与输出 >>> print(Name: %s, score: %d % (Jack, 89)) Name: Jack, score: 89>>> print(Hello, world!) #逗号连接 Hello world!a raw_input("a:") #捕获原始输入,返回字符串 b …

资料验证的asp.net程序
<!-------资料验证:天乐comezxnsina.com------------> <!-------比较简单,以前写的,若有纰漏,请跟我联系----------> <Html> <Body bgcolor"White"> <H3>Validator(资料验证)控制元件<…

iphone UIView的一些基本方法理解
原文链接地址:http://www.cocoachina.com/bbs/read.php?tid38766UIView的一些基本方法理解UIView的一些基本方法理解:loadView、viewDidLoad、viewDidUnload、viewWillAppear、viewWillDisappear经常使用UIView以及它的子类,一般对于init:&a…
收藏!美国博士明确给出Python的高效学习技巧
我见过市面上很多的 Python 讲解教程和书籍,他们大都这样讲 Python 的:先从 Python 的发展历史开始,介绍 Python 的基本语法规则,Python 的 list, dict, tuple 等数据结构,然后再介绍字符串处理和正则表达式࿰…

pl/sql中三种游标循环效率对比
pl/sql中三种游标循环效率对比 - Oracle数据库栏目 - 红黑联盟 http://www.2cto.com/database/201307/224636.html转载于:https://blog.51cto.com/yweaner/1873294

UpdateData函数(转)
UpdateData,顾名思义,是用来刷新数据的。 UpdateData(TRUE) -- 刷新控件的值到对应的变量 UpdateData(FALSE) -- 拷贝变量值到控件显示例如,窗口中用 DDX_Text(pDX, IDC_EDIT1, m_usercode); 将IDC_EDIT1编辑框控件与m_usercode变量做了关联&…

PEAR, PECL和Perl的区别
PEAR是PHP扩展与应用库(the PHP Extension and Application Repository)的缩写。它是一个PHP扩展及应用的一个代码仓库,简单地说,PEAR就是PHP的CPAN。 PECL (PHP Extension Community Library),…
永远不要对 AI 说:“我不行!”
最近这些年,如果我要问什么技术最值钱,我想超过90%的人都会说是:人工智能。确实,随着近些年人工智能发展与普及,AI研发岗早已成为编程领域薪水最高的岗位之一。但扎心的是,一提到 AI ,相信绝大部…

ThoughtWorks雷达上的新奇变化
与往常一样,ThoughtWorks技术雷达涵盖了四方面内容:语言与框架、平台、技术和工具,而且其中每个领域都会有四方面内容:采用、试用、评估及保留。本文列举了相关领域中较新和值得注意的内容。\\语言与框架\\采用: Ember.js由于其生…

用于时序动作提名生成任务,爱奇艺提出BC-GNN图神经网络 | ECCV 2020
时序动作提名生成任务可以从未处理的长视频中定位出包含动作内容的片段,对视频理解以及时序行为检测任务等有着重要的作用。随着视频数量的激增以及视频内容的丰富,对时序动作提名算法的关注和需求也得到巨大提升。然而目前的方法多采用先生成起止边界&a…

剖析ASP.NET下部构造
crystal译yesky(前面我已说过ASP.NET拥有全新的下部构造)当我说到全新的下部构造……我得再次强调,是全新的下部构造! 它不只 是 ASP 的一个简单变化. 在此引入收管代码(managed code)这样一个全新概念,它横贯整个视窗开发平台. 受管代码在 NGWS Runtime下运行. NGWS Runtime是…

超大磁盘分区工具parted使用介绍(一)
使用parted GNU Parted有两种运行模式:命令行模式和交互模式。 1.命令行模式的选项 当你调用命令行模式时,parted的语法是这样的: 格式1# parted [option] device 格式2# parted [option] device [command [argument]] 格式1&am…

Sea.js学习4——Sea.js的配置
可以对 Sea.js 进行配置,让模块编写、开发调试更方便。 seajs.config seajs.config(options) 用来进行配置的方法。 seajs.config({// 别名配置alias: {es5-safe: gallery/es5-safe/0.9.3/es5-safe,json: gallery/json/1.0.2/json,jquery: jquery/jquery/1.10.1/jqu…

SQL Server 性能基线和监控
就讲讲监控那些值,基线抓的是那些值。如何做告警 环境:windows 2008r2,sql server 2008r2 sp1 性能基线: cpu: \Processor(_Total)\% Processor Time \Processor(_Total)\% Privileged Time \SQLServer:SQL Statistics\Bat…