`
elitesunry
  • 浏览: 36270 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

C 宏定义小结

阅读更多

1,防止一个头文件被重复包含

#
ifndef
COMDEF_H

#defineCOMDEF_H

//
头文件内容

#
endif


2,
重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植。

typedefunsignedcharboolean
;/*Booleanvaluetype.*/

typedefunsignedlongint
uint32;/*Unsigned32bitvalue*/

typedef
unsignedshortuint16;/*Unsigned16bitvalue*/

typedef
unsignedcharuint8;/*Unsigned8bitvalue*/

typedefsignedlongint
int32;/*Signed32bitvalue*/

typedef
signedshortint16;/*Signed16bitvalue*/

typedef
signedcharint8;/*Signed8bitvalue*/

//
下面的不建议使用

typedefunsignedcharbyte;/*Unsigned8bit
valuetype.*/

typedefunsignedshortword;/*Unsinged
16bitvaluetype.*/

typedefunsignedlongdword
;/*Unsigned32bitvaluetype.*/

typedefunsigned
charuint1;/*Unsigned8bitvaluetype.*/

typedefunsigned
shortuint2;/*Unsigned16bitvaluetype.*/

typedefunsigned
longuint4;/*Unsigned32bitvaluetype.*/

typedefsigned
charint1;/*Signed8bitvaluetype.*/

typedefsigned
shortint2;/*Signed16bitvaluetype.*/

typedeflongint
int4;/*Signed32bitvaluetype.*/

typedef
signedlongsint31;/*Signed32bitvalue*/

typedef
signedshortsint15;/*Signed16bitvalue*/

typedef
signedcharsint7;/*Signed8bitvalue*/

3,
得到指定地址上的一个字节或字

#defineMEM_B(x)(*((byte*)(x)))

#defineMEM_W(x)(*((word*)(x)))

4,求最大值和最小值

#defineMAX(x,y)(((x)>(y))?(x):(y))

#defineMIN(x,y)(((x)<(y))?(x):(y))

5,得到一个field在结构体(
struct)
中的偏移量

#defineFPOS(type,field)\

/*lint-e545*/((
dword
)&((type*)0)->field)/*lint+e545*/

6,
得到一个结构体中field所占用的字节数

#defineFSIZ(type,field)
sizeof
(((type*)0)->field)

7,
按照LSB格式把两个字节转化为一个Word

#defineFLIPW(ray)((((word)(ray)[0])*256)+(ray)[1])

8,按照LSB格式把一个Word转化为两个字节

#defineFLOPW(ray,
val
)\

(ray)[0]=((
val
)/256);\

(ray)[1]=((
val
)&0xFF)

9,
得到一个变量的地址(word宽度)

#defineB_PTR(
var)((byte*)(void*)&(var
))

#defineW_PTR(
var)((word*)(void*)&(var
))

10,
得到一个字的高位和低位字节

#defineWORD_LO(xxx)((byte)((word)(xxx)&255))

#defineWORD_HI(xxx)((byte)((word)(xxx)>>8))

11,返回一个比X大的最接近的8的倍数

#defineRND8(x)((((x)+7)/8)*8)

12,将一个字母转换为大写

#defineUPCASE(c)(((c)>=''a''&&(c)<=''z'')?((c)-0x20):(c))

13,判断字符是不是10
进值的
数字

#defineDECCHK(c)((c)>=''0''&&(c)<=''9'')

14,判断字符是不是16
进值的
数字

#defineHEXCHK(c)(((c)>=''0''&&(c)<=''9'')||\

((c)>=''A''&&(c)<=''F'')||\

((c)>=''a''&&(c)<=''f''))

15,防止溢出的一个方法

#defineINC_SAT(
val)(val=((val)+1>(val))?(val)+1:(val
))

16,
返回数组元素的个数

#defineARR_SIZE(a)(
sizeof((a))/sizeof
((a[0])))

17,
返回一个无符号数n尾的值MOD_BY_POWER_OF_TWO(X,n
)=X%(2^n)

#defineMOD_BY_POWER_OF_TWO(
val,mod_by
)\

((
dword)(val)&(dword)((mod_by
)-1))

18,
对于IO空间映射在存储空间的结构,输入输出处理

#define
inp
(port)(*((volatilebyte*)(port)))

#define
inpw
(port)(*((volatileword*)(port)))

#define
inpdw(port)(*((volatiledword
*)(port)))

#define
outp(port,val)(*((volatilebyte*)(port))=((byte)(val
)))

#define
outpw(port,val)(*((volatileword*)(port))=((word)(val
)))

#define
outpdw(port,val)(*((volatiledword*)(port))=((dword)(val
)))

19,使用一些宏
跟踪调试

ANSI
标准说明了五个预定义的宏名。它们是:


_LINE_

_FILE_

_DATE_

_TIME_

_STDC_

如果编译不是标准的,则可能仅支持以上宏名中的几个,或根本不支持。记住编译程序


也许还提供其它预定义的宏名。


_LINE_
_FILE_宏指令在有关#l
ine的部分中已讨论,这里讨论其余的宏名。

_DATE_
宏指令含有形式为月//年的串,表示源文件被翻译到代码时的日期。


源代码翻译到目标代码的时间作为串包含在_TIME_中。
串形式为时:分:秒。

如果实现是标准的,则宏_STDC_含有十进制常量1。如果它含有任何其它数,则实现是


非标准的。


可以定义宏,例如
:

当定义了_DEBUG,输出数据信息和所在文件所在行


#
ifdef_DEBUG

#defineDEBUGMSG(
msg,date)printf(msg);printf(%d%d%d,date,_LINE_,_FILE
_)

#else

#defineDEBUGMSG(
msg,date
)

#
endif



20,
宏定义防止使用是错误

用小括号包含。


例如:#defineADD(
a,b)a+b

do{}while(0)语句包含多语句防止错误


例如:#
difneDO(a,b)a+b;\

a++;

应用时:if(.)

DO(
a,b);//产生错误

else

解决方法:#
difneDO(a,b)do{a+b;\

a++;}while(0)
宏中"#""##"的用法
一、一般用法

我们使用#把宏参数变为一个字符串,##把两个宏参数贴合在一起
.
用法
:
#include<
cstdio>
#include<
climits
>
usingnamespacestd;

#defineSTR(s)#s
#defineCONS(
a,b)int(a##e##b
)

int
main()
{
printf(STR(vck));//输出字符串"vck
"
printf("%d\n",CONS(2,3));//2e3
输出:2000
return0;
}

二、当宏参数是另一个宏的时候

需要注意的是凡宏定义里有用''#''''##''的地方宏参数是不会再展开
.

1,
''#''''##''的情况

#defineTOW(2)
#defineMUL(
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,
当有''#''''##''的时候

#defineA(2)
#defineSTR(s)#s
#defineCONS(
a,b)int(a##e##b)

printf("intmax:%s\n",STR(INT_MAX));//INT_MAX#include<climits
>
这行会被展开
为:
printf("intmax:%s\n","INT_MAX");

printf
("%s\n",CONS(A,A));//compileerror
这一行则是:
printf("%s\n",int(AeA));

INT_MAX
A都不会再被展开,然而解决这个问题的方法很简单.加多一层中间转换宏.
加这层宏的用意是把所有宏的参数在这层里全部展开,那么在转换宏里的那一个宏(_STR)就能得到正确的宏参数
.

#defineA(2)
#define_STR(s)#s
#defineSTR(s)_STR(s)//
转换宏

#define_CONS(
a,b)int(a##e##b)
#defineCONS(
a,b)_CONS(a,b)//
转换宏

printf("intmax:%s\n",STR(INT_MAX));//INT_MAX,int型的最大值,为一个变量#include<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)typevar##line
#define__ANONYMOUS0(type,line)___ANONYMOUS1(type,_anonymous,line)
#defineANONYMOUS(type)__ANONYMOUS0(type,__LINE__)
例:ANONYMOUS(staticint);:staticint_anonymous70;70
表示该行行号;
第一层:ANONYMOUS(static
int);-->__ANONYMOUS0(staticint,__LINE__);
第二层:-->___ANONYMOUS1(staticint
,_anonymous,70);
第三层:-->staticint
_anonymous70;
即每次只能解开当前层的宏,所以__LINE__在第二层才能被解开;

2
、填充结构

#defineFILL(a){a,#a}

enumIDD{OPEN,CLOSE};
typedefstruct
MSG{
IDDid;
constchar*
msg
;
}MSG;

MSG_
msg
[]={FILL(OPEN),FILL(CLOSE)};
相当于:
MSG_
msg[]={{OPEN,"OPEN"},
{CLOSE,"CLOSE"}};

3
、记录文件名
#define_GET_FILE_NAME(f)#f
#defineGET_FILE_NAME(f)_GET_FILE_NAME(f)
staticcharFILE_NAME[]=GET_FILE_NAME(__FILE__);

4
、得到一个数值类型所对应的字符串缓冲大小

#define_TYPE_BUF_SIZE(type)
sizeof#type
#defineTYPE_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];

From:http://blog.csdn.net/fengyuruhui/archive/2007/08/16/1747090.aspx

分享到:
评论

相关推荐

    C++中的常量定义小结

    一般来说,使用C语言编程时我们都习惯在代码当中使用C当中的宏定义来定义一个数值常量: #define MY_CONST 7 在C++开发项目时,也会经常存在沿袭C当中常量用法情况。所以,如下的一种写法看起来反倒觉得有些不正宗...

    谭浩强c语言程序设计

    不多说,很经典的。 谭浩强c语言程序设计(pdf版) 1 C语言概述 1.1 C语言的发展过程 1.2 当代最优秀的程序设计语言 1.3 C语言版本 1.4 C语言的特点 1.5 面向对象的程序设计语言 ...13.8 本章小结

    谭浩强 C语言程序设计 教程全书 Word版

    谭浩强 C语言程序设计 教程全书 Word版,内容预览: 1 C语言概述 2 1.1 C语言的发展过程 2 1.2 当代最优秀的程序设计语言 2 1.3 C语言版本 2 1.4 C语言的特点 3 1.5 面向对象的程序设计语言 3 ...13.8 本章小结 15

    谭浩强版c语言程序设计

    10.8 有关指针的数据类型和指针运算的小结 167 10.8.1 有关指针的数据类型的小结 167 10.8.2 指针运算的小结 167 10.8.3 void指针类型 168 11 结构体与共用体 11.1 定义一个结构的一般形式 170 11.2 结构类型变量的...

    《C语言程序设计》谭浩强

    C语言的发展过程 1.2 当代最优秀的程序设计语言 1.3 C语言版本 1.4 C语言的特点 1.5 面向对象的程序设计语言 1.6 C和C++ 1.7 简单的C程序介绍 1.8 输入和输出函数 1.9 C源程序的结构特点 ...13.8 本章小结

    C语言全书word版CHAR09

    9 预处理命令 1 9.1 概述 1 9.2 宏定义 1 9.2.1 无参宏定义 1 9.2.2 带参宏定义 4 9.3 文件包含 8 9.4 条件编译 9 9.5 本章小结 11

    c语言(编写程序最佳参考资料)

    9.2.1 无参宏定义... 1 9.2.2 带参宏定义... 4 9.3 文件包含... 8 9.4 条件编译... 9 9.5 本章小结... 11 10 指针 10.1 地址指针的基本概念 10.2 变量的指针和指向变量的指针变量 10.2.1 定义一个指针变量 ...

    c语言程序设计(第三版)

    1 C语言概述 2 1.1 C语言的发展过程 2 1.2 当代最优秀的程序设计语言 2 1.3 C语言版本 2 1.4 C语言的特点 3 1.5 面向对象的程序设计语言 3 1.6 C和C++ 3 1.7 简单的C程序介绍 4 ...13.8 本章小结 15

    谭浩强c语言word版

    目录: 1 C语言概述 1.1 C语言的发展过程 1.2 当代最优秀的程序设计语言 1.3 C语言版本 1.4 C语言的特点 1.5 面向对象的程序设计语言 1.6 C和C++ 1.7 简单的C程序介绍 1.8 输入和输出函数 ...13.8 本章小结

    谭浩强C程序设计第三版

    C语言教程 C语言概述 7 C语言的发展过程 7 当代最优秀的程序设计语言 7 C语言版本 7 C语言的特点 7 面向对象的程序设计语言 8 C和C++ 8 简单的C程序介绍 8 输入和输出函数 9 ...本章小结 213

    Linux c中define的用法小结

    define的用法只是一种纯粹的替换功能,宏定义的替换是预处理器处理的替换。  一:简单的宏定义用法  格式:#define 标识符 替换内容  替换的内容可以是数字,字符,字符串,特殊字符和空格,后面是什么内容就会...

    谭浩强C语言教程Word版

    23 &lt;br/&gt;9 预处理命令 1 9.1 概述 1 9.2 宏定义 1 9.2.1 无参宏定义 1 9.2.2 带参宏定义 4 9.3 文件包含 8 9.4 条件编译 9 9.5 本章小结 11 &lt;br/&gt;10 指针 1 10.1 地址指针...

    C语言入门经典(第4版)--源代码及课后练习答案

    1.10 小结 18 1.11 习题 18 第2章 编程初步 19 2.1 计算机的内存 19 2.2 什么是变量 21 2.3 存储数值的变量 21 2.3.1 整数变量 21 2.3.2 变量的命名 25 2.3.3 变量的使用 26 2.3.4 变量的初始化 28 2.3.5 ...

    谭浩强C语言程序设计,C++程序设计,严蔚敏数据结构,高一凡数据结构算法分析与实现.rar )

    10.8 有关指针的数据类型和指针运算的小结 167 10.8.1 有关指针的数据类型的小结 167 10.8.2 指针运算的小结 167 10.8.3 void 指针类型 168 11 结构体与共用体 11.1 定义一个结构的一般形式 170 11.2 结构类型变量的...

    c语言程序设计标准教程

    在有时也可用宏定义来代替typedef的功能,但是宏定义是由预处理完成的,而typedef则是在编译时完成的,后者更为灵活方便。 本章小结 1. 枚举是一种基本数据类型。枚举变量的取值是有限的,枚举元素是常量,不是...

    C语言程序设计标准教程

    程序定义了文件指针fp,以读文本文件方式打开文件“e10_1.c”, 并使fp指向该文件。如打开文件出错, 给出提示并退出程序。程序第12行先读出一个字符,然后进入循环, 只要读出的字符不是文件结束标志(每个文件末有...

    C++ vector的用法小结

    c++ vector用法 C++内置的数组支持容器的机制,但是它不支持容器抽象的语义。...一、 定义和初始化 vector&lt; typeName&gt; v1; //默认v1为空,故下面的赋值是错误的v1[0]=5; vector&lt;typeName&gt;v2(v1); 或v2

    程序设计基础(C) 视频.txt

    5.5.2宏定义106 5.5.3条件编译108 5.6多文件结构109 本章小结110 习题110 第6章指针114 6.1指针的概念114 6.1.1指针变量的声明115 6.1.2指针变量的初始化与引用115 6.2指针运算116 6.2.1运算符“ [1]

    C++大学教程,一本适合初学者的入门教材(part2)

    小结 术语 自测练习 自测练习答案 练习 第2章 控制结构 2.1 简介 2.2 算法 2.3 伪代码 2.4 控制结构 2.5 if选择结构 2.6 if/e1se选择结构 2.7 while重复结构 2.8 构造算法:实例研究1(计数器控制重复) 2.9 ...

Global site tag (gtag.js) - Google Analytics