当前位置: 首页 > 科技观察

要想写好C语言,漂亮的宏定义很重要!

时间:2023-03-21 18:23:52 科技观察

写好C语言,漂亮的宏定义很重要!使用宏定义可以防止错误,提高可移植性、可读性、方便性等,下面列出一些成熟软件中常用的宏定义。1.防止一个头文件被重复包含1#ifndefCOMDEF_H2#defineCOMDEF_H3//头文件内容4#endif2.重新定义一些类型,防止因不同平台和编译器的差异导致类型的字节数不同,便于移植。1typedefunsignedchar布尔值;/*布尔值类型。*/2typedefunsignedlongintuint32;/*无符号32位值*/3typedefunsignedshortuint16;/*无符号16位值*/4typedefunsignedcharuint8;/*无符号8位值*/5typedefsignedlongintint32;/*带符号的32位值*/6typedefsignedshortint16;/*有符号的16位值*/7typedefsignedcharint8;/*有符号8位值*/不建议使用:1typedefunsignedcharbyte;/*无符号8位值类型。*/2typedef无符号短字;/*未签名的16位值类型。*/3typedef无符号长双字;/*无符号32位值类型。*/4typedefunsignedcharuint1;/*无符号8位值类型。*/5typedefunsignedshortuint2;/*无符号16位值类型。*/6typedefunsignedlonguint4;/*无符号32位值类型。*/7typedefsignedcharint1;/*有符号的8位值类型。*/8typedefsignedshortint2;/*有符号的16位值类型。*/9typedeflongintint4;/*带符号的32位值类型。*/10typedef签名长sint31;/*带符号的32位值*/11typedefsignedshortsint15;/*带符号的16位值*/12typedefsignedcharsint7;/*带符号的8位值*/3.获取字节或字1#defineMEM_B(x)(*((byte*)(x)))2#defineMEM_W(x)(*((word*)(x)))4.求最大值和最小值1#defineMAX(x,y)(((x)>(y))?(x):(y))2#defineMIN(x,y)(((x)<(y))?(x):(y))5.获取结构体中某个字段的偏移量(struct)1#defineFPOS(type,field)\2/*lint-e545*/((dword)&((type*)0)->field)/*lint+e545*/6。获取结构体中某个字段占用的字节数1#defineFSIZ(type,field)sizeof(((type*)0)->field)7.根据LSB格式将两个字节转换成一个Word1#defineFLIPW(ray)((((word)(ray)[0])*256)+(ray)[1])8.将Word转换为LSB格式两个字节1#defineFLOPW(ray,val)\2(ray)[0]=((val)/256);\3(射线)[1]=((val)&0xFF)9.获取一个变量地址(字宽)1#defineB_PTR(var)((byte*)(void*)&(var))2#defineW_PTR(var)((word*)(void*)&(var))10。获取一个字的高低字节1#defineWORD_LO(xxx)((byte)((word)(xxx)&255))2#defineWORD_HI(xxx)((byte)((word)(xxx)>>8))11.返回大于X1的最接近8的倍数#defineRND8(x)((((x)+7)/8)*8)12。将字母转换为大写1#defineUPCASE(c)(((c)>='a'&&(c)<='z')?((c)-0x20):(c))13.判断字符是否为十进制数1#defineDECCHK(c)((c)>='0'&&(c)<='9')14.判断字符是否为十六进制数1#defineHEXCHK(c)(((c)>='0'&&(c)<='9')||\2((c)>='A'&&(c)<='F')||\3((c)>='a'&&(c)<='f'))15.一种防止溢出的方法1#defineINC_SAT(val)(val=((val)+1>(val))?(val)+1:(val))16.返回数组元素个数1#defineARR_SIZE(a)(sizeof((a))/sizeof((a[0])))17。返回一个无符号的n尾值MOD_BY_POWER_OF_TWO(X,n)=X%(2^n)1#defineMOD_BY_POWER_OF_TWO(val,mod_by)\2((dword)(val)&(dword)((mod_by)-1))18。IO空间映射到存储空间的结构,输入输出处理:1#defineinp(port)(*((volatilebyte*)(port)))2#defineinpw(port)(*((volatileword*)(port)))3#defineinpdw(port)(*((volatiledword*)(port)))4#defineoutp(port,val)(*((volatilebyte*)(port))=((byte)(val)))5#defineoutpw(port,val)(*((volatileword*)(port))=((word)(val)))6#defineoutpdw(port,val)(*((volatiledword*)(port))=((dword)(val)))19.使用一些宏来跟踪DebugANSI标准规定了五个预定义的宏名,分别是:1_LINE_2_FILE_3_DATE_4_TIME_5_STDC_如果编译不标准,可能只支持上面的几个宏名,或者根本不支持all请记住,编译器可能还会提供其他预定义的宏名称。_LINE_和_FILE_宏在#行的部分中讨论,其余的宏名称在此处讨论。_DATE_宏包含一个格式为月/日/年的字符串,表示源文件被翻译成代码的日期。将源代码转换为目标代码的时间作为字符串包含在_TIME_中。字符串格式为小时:分钟:秒。如果实现是标准的,宏_STDC_包含十进制常量1。如果它包含任何其他数字,则实现是非标准的。可以定义宏,例如:定义_DEBUG时,输出数据信息和文件所在行。1#ifdef_DEBUG2#defineDEBUGMSG(msg,date)printf(msg);printf(“%d%d%d”,date,_LINE_,_FILE_)3#else4#defineDEBUGMSG(msg,date)5#endif20。宏定义包含在括号中以防止使用错误。例如:1#defineADD(a,b)(a+b)使用do{}while(0)语句包含多个语句以防止出错,例如:1#difneDO(a,b)a+b;\2a++;应用While:1if(….)2DO(a,b);//产生错误3else解决方案:1#defineDO(a,b)do{a+b;\2a++;}while(0)