C 语言常用方法技巧
C语言常用方法技巧
除法向上取整
#defineDIV_ROUND_UP(n,d)(((n)+(d)-1)/(d))
大端小端选择
low-endianorhigh-endian
typedefunion{ shortW;/*Wordaccess*/ struct{/*Byteaccess*/ #ifdefLOW_ENDIAN bytelow,high;/*inlow-endianarch*/ #else bytehigh,low;/*inhigh-endianarch*/ #endif }B; }word;
求余数运算
a=a%8; => a=a&7;
说明:位运算只需一个指令周期;取余通常需要调用子程序。
平方运算
a=pow(a,2.0); => a=a*a;
说明:内置乘法运算器的处理器中,乘法运算比求平方运算更快;即使没有内置乘法运算器,乘法运算的子程序也比平方运算子程序效率高。
移位实现乘除法运算
a=a*4; b=b/4; => a=a<<2; b=b>>2;
说明:通常乘以或者除以2n,可使用移位方法代替。
a=a*9; => a=(a<<3)+a;
while循环和do...while循环
说明:do...while循环编译后生成的代码长度短于while循环。
重定义类型,扩展移植性
typedefunsignedcharboolean;/*Booleanvaluetype.*/ typedefunsignedlongintuint32;/*Unsigned32bitvalue*/ typedefunsignedshortuint16;/*Unsigned16bitvalue*/ typedefunsignedcharuint8;/*Unsigned8bitvalue*/ typedefsignedlongintint32;/*Signed32bitvalue*/ typedefsignedshortint16;/*Signed16bitvalue*/ typedefsignedcharint8;/*Signed8bitvalue*/
得到指定地址上的一个字节或字
typedefunsignedcharbyte;/*Unsigned8bitvaluetype*/ typedefunsignedshortword;/*Unsigned16bitvaluetype*/ #defineMEM_B(x)(*((byte*)(x))) #defineMEM_W(x)(*((word*)(x)))
求取极值
#defineMAX(x,y)((x)>(y)?(x):(y)) #defineMIN(x,y)((x)<(y)?(x):(y))
得到一个field在结构体(struct)中的偏移量
typedefunsignedlongdword;/*Unsigned32bitvaluetype*/ #defineFPOS(type,field)\ ((dword)&((type*)0)->field)
得到一个结构体中field所占用的字节数
#defineFSIZE(type,field)\ (sizeof(((type*)0)->field))
按照LSB格式把一个word(16bit)转换成两个字节
#defineFLOPW(ray,val)\ do{\ (ray)[0]=((val)>>8);\ (ray)[1]=((val)&0xFF);\ }while(0);
得到一个变量的地址
typedefunsignedcharbyte;/*Unsigned8bitvaluetype*/ typedefunsignedshortword;/*Unsigned16bitvaluetype*/ #defineB_PTR(var)((byte*)(void*)&(var)) #defineW_PTR(var)((word*)(void*)&(var))
得到一个字节的低位和高位
typedefunsignedcharbyte;/*Unsigned8bitvaluetype*/ typedefunsignedshortword;/*Unsigned16bitvaluetype*/ #defineWORD_L(var)((byte)(word)(var)&(0xFF)) #defineWORD_H(var)((byte)(word)(var)>>(8))
返回一个比X大的接近8的倍数
#defineRND8(x)((((x)+7)>>3)<<3)
防止溢出的方法
#defineINC_SAT(val)\ ((val)=(((val)+1)>(val))?((val)+1):(val))
返回数组元素的个数
#defineARR_SIZE(a)\ ((sizeof(a))/(sizeof(a[0])))
返回一个无符号数的后n位数
typedefunsignedlongdword;/*Unsigned32bitvaluetype*/ #defineMOD_BY_POWER_OF_TWO(val,mod_by)\ ((dword)(val)&(dword)(2<<(mod_by)-1))
IO空间映射在存储空间中的结构
typedefunsignedcharbyte;/*Unsigned8bitvaluetype*/ typedefunsignedshortword;/*Unsigned16bitvaluetype*/ typedefunsignedlongdword;/*Unsigned32bitvaluetype*/ #defineoutp(port)(*((volatilebyte*)(port))) #defineoutpw(port)(*((volatileword*)(port))) #defineoutpdw(port)(*((volatiledword*)(port))) #defineinp(port,val)(*((volatilebyte*)(port)))=(byte)(val) #defineinpw(port,val)(*((volatileword*)(port)))=(word)(val) #defineinpdw(port,val)(*((volatiledword*)(port)))=(dword)(val)
宏中"#"和"##"的用法
一、使用"#"把宏参数变为一个字符串,用"##"把两个宏参数贴合在一起。
#defineSTR(val)(#val) #defineCONS(a,b)(int)(a##e##b) -> STR(hello)==>"hello" CONS(2,3)==>2000//2e3
二、当宏参数是另一个宏的时候
需要注意的是凡宏定义里有用'#'或'##'的地方宏参数是不会再展开.
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 ==> 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
输出为:intmax: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(staticint);
-->__ANONYMOUS0(staticint,__LINE__);
第二层:-->___ANONYMOUS1(staticint,_anonymous,70);
第三层:-->staticint_anonymous70;
即每次只能解开当前层的宏,所以__LINE__在第二层才能被解开;
2、填充结构
#defineFILL(a){a,#a} enumIDD{OPEN,CLOSE}; typedefstructMSG{ 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) charbuf[TYPE_BUF_SIZE(INT_MAX)]; -->charbuf[_TYPE_BUF_SIZE(0x7fffffff)]; -->charbuf[sizeof"0x7fffffff"];
这里相当于:charbuf[11];
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持毛票票!