Open
Description
各种宏定义用法整理
C语言ASCII字符、16进制和BCD码值互转,各种好用的宏定义取值
1、把Ascii字符转16进制
/***************************
函数名:Ascii2Hex
功能描述:把Ascii字符转16进制
参数:Ascii字符
返回:16进制
***************************/
unsigned char Ascii2Hex( unsigned char bAscii )
{
unsigned char bHex = 0;
if( ( bAscii >= 0 ) && ( bChar <= 9 ) )
{
bHex = bAscii + 0x30;
}
else if( ( bAscii >= 10 ) && ( bAscii <= 15 ) )
{
bHex = bAscii + 0x37;
}
else
{
bHex = 0xff;
}
return bHex;
}
2、把16进制转Ascii字符
/***************************
函数名:Hex2Ascii
功能描述:把16进制转Ascii字符
参数:16进制
返回:Ascii字符
***************************/
unsigned char Hex2Ascii( unsigned char bHex )
{
unsigned char bAscii = 0;
if( ( bHex >= '0' ) && ( bHex <= '9' ) )
{
bAscii = bHex - '0';
}
else if( ( bHex >= 'A' ) && ( bHex <= 'F' ) )
{
bAscii = bHex - '7';
}
else if( ( bHex >= 'a' ) && ( bHex <= 'f' ) )
{
bAscii = bHex - 0x57;
}
else
{
bAscii = 0xff;
}
return bAscii;
}
3、把16进制转BCD值
/***************************
函数名:Hex2Bcd
功能描述:把16进制转BCD值
参数:16进制值
返回:BCD值
***************************/
u_8 Hex2Bcd( u_8 HexCode )
{
return( ( HexCode % 10 ) + ( HexCode / 10 * 16 ) );
}
4、把BCD值转2进制
/***************************
函数名:Bcd2Bin
功能描述:把BCD值转2进制
参数:BCD值
返回:2进制值
***************************/
u_8 Bcd2Bin( u_8 BcdCode )
{
return( ( ( ( BcdCode >> 4 ) & 0x0F ) * 10 ) + ( BcdCode & 0x0F ));
}
5、把2进制转BCD值
/***************************
函数名:Bin2BCD
功能描述:把2进制转BCD值
参数:2进制值
返回:BCD值
***************************/
u_8 Bin2BCD( u_8 BinCode )
{
return( ( ( (BinCode)/10 ) << 4 ) + ( (BinCode) %10 ));
}
6、把x值的第i位置为1
/********把x值的第i位置为1*************/
#define X_SETBIT( x , i ) ( (x) |= ( 0x1 << (i) ))
7、把x值的第i位清为0
/**********把x值的第i位清为0**********/
#define X_CLRBIT( x , i ) ( (x) &= ( ~( 0x01 << (i) )))
8、判断x值的第i位是否为1
/*********判断x值的第i位是否为1**********/
#define X_CHKBIT( x , i ) ( ((x) >> (i) ) & 0x01 )
9、x,y值中的最小值
/*********x,y值中的最小值**********/
#define X_MIN( x ,y ) (((x)>(y))?(y):(x))
10、x,y值中的最大值
/*********x,y值中的最大值**********/
#define X_MAX( x ,y ) (((x)>(y))?(x):(y))
11、取i值的低8位
/*********取i值的低8位**********/
#define GET_4_BYTE(i) (u_8)( ( (i) & 0xFF ) >> 0 )
12、取i值的8-16位
/*********取i值的8-16位**********/
#define GET_3_BYTE(i) (u_8)( ( (i) & 0xFF00 ) >> 8 )
13、取i值的16-24位
/*********取i值的16-24位**********/
#define GET_2_BYTE(i) (u_8)( ( (i) & 0xFF0000 ) >> 16 )
14、取i值的24-32位
/*********取i值的24-32位**********/
#define GET_1_BYTE(i) (u_8)( ( (i) & 0xFF000000 ) >> 24 )
15、4个字节为int型变量
/*********4个字节为int型变量**********/
#define BYTE_TO_INT( byte,byte1,byte2,byte3 ) ( (byte<<24) | (byte1 << 16) | (byte2 << 8) | byte3 )
16、2个字节为short型变量
/*********2个字节为short型变量**********/
#define BYTE_TO_SHORT( byte ,byte1) ( (byte<<8) | byte1 )
17、int型变量为4个字节
/*********int型变量为4个字节**********/
#define INT_TO_BYTE( Val,byte ) do{ (byte)[0] = ((Val)>>24)&0xff;\
(byte)[1] = ((Val)>>16)&0xff;\
(byte)[2] = ((Val)>>8)&0xff;\
(byte)[3] = ((Val))&0xff;\
}while(0)
18、short型变量为2个字节
/*********short型变量为2个字节**********/
#define SHORT_TO_BYTE( Val ,byte) do{ (byte)[0] = ((Val)>>8)&0xff;\
(byte)[1] = (Val)&0xff;\
}while(0)
19、标准时间time转换字符串输出
/*********标准时间time转换字符串输出**********/
#define TIME_2_STR(t, str) do{ tm_t tmtime;\
gmtime_r( (time_t *)&t,&tmtime );\
sprintf(str,"%04d-%02d-%02d %02d:%02d:%02d",1900 + tmtime.tm_year, tmtime.tm_mon + 1, \
tmtime.tm_mday,tmtime.tm_hour, tmtime.tm_min, tmtime.tm_sec);\
}while(0)
20、IP值转换IP字符串输出
/*********IP值转换IP字符串输出**********/
#define IPADDR_2_STR(lIp, str) do{ u_8 ipaddr[4];\
memcpy (&(ipaddr[0]), &(lIp), 4);\
sprintf(str,"%03d.%03d.%03d.%03d",ipaddr[0],ipaddr[1],ipaddr[2],ipaddr[3]);\
}while(0)
一、字符串化操作符#
-
#
的功能:将#后面的宏参数转化成字符串。 -
使用条件:只能用于有传入参数的宏定义中,且#必须置于宏定义体中的参数名前。
#include<stdio.h>
// s是宏参数
#define Str(s) #s //功能:使用Str(s)将s转化为字符串
int main()
{
printf(Str(HelloWorld));
return;
}
//输出:HelloWorld
3.对空格的处理
#define example1(instr) #instr
stringstr=example1(abc); 将会展成:string str="abc";
🥝 a、忽略传入参数名前面和后面的空格。
如:str=example1( abc ); 将会被扩展成 str="abc";
🥝 b、当传入参数名间存在空格时,编译器将自动连接各个子字符串,用每个子字符串中只一个空格连接,忽略多余一个空格。
如:str=exapme1( abc def ); 将会被扩展成 str="abc def";
- 宏定义作为宏参数,不展开,仍然作为字符串字面信息输出。
#include <limits.h>
#include <stdio.h>
#define STR(s) #s
int main()
{
// INT_MAX是某个文件中定义的宏,
printf("int max: %s\n", STR(INT_MAX)); // 输出int max: INT_MAX
return 0;
}
二、符号连接操作符 ##
-
##
的功能: 将前后两个标识符连接形成一个标识符。 -
使用条件:只能用于有传入参数的宏定义中,且##必须置于宏定义体中的参数名前。
#include<stdio.h>
#define Var(x) var##x
int main()
{
int Var(1)=1,Var(2)=2,Var(3)=3;
printf("var1=%d\n",var1);
printf("var2=%d\n",var2);
printf("var3=%d\n",var3);
return 0;
}
3.注意
a、当用##连接形参时,##前后的空格可有可无。
如:#define exampleNum(n) num ## n 相当于 #define exampleNum(n) num##n
b、连接后的实际参数名,必须为实际存在的参数名或是编译器已知的宏定义。连接之后只是组成了一个参数名,并没有定义,因此要求这个参数名需要是已经存在或者说已经被定义了的参数或宏定义。
c、当宏参数是另一个宏时,凡宏定义中存在#或##的地方,宏参数不会再展开。
( 只有当前宏生效, 参数里的宏!不会生效 !)
① 宏定义不存在’#‘和’##'的情况
#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).
② 宏定义存在’#‘或’##'的时候(#在上方有讲解)
#include <limits.h>
#include <stdio.h>
#define A 2
#define CONS(a,b) (int)(a##e##b) //ps:##放到宏参数后面相当于一个连接 无其他作用
int main()
{
// 由于A是宏,且作为宏CONS的参数,并且宏CONS##符号,所以A不能被解引用,因此上方程序编译报错。
printf("%d\n", CONS(A, A)); // compile error 无法展开
//printf("%d\n", (int)(AeA));
return 0;
}
// 报错信息如下:
main.c: In function ‘main’:
main.c:8:22: error: ‘AeA’ undeclared (first use in this function)
8 | printf("%d\n", CONS(A, A)); // compile error 无法展开
| ^
main.c:5:26: note: in definition of macro ‘CONS’
5 | #define CONS(a,b) (int)(a##e##b) //ps:##放到宏参数后面相当于一个连接 无其他作用
| ^
main.c:8:22: note: each undeclared identifier is reported only once for each function it appears in
8 | printf("%d\n", CONS(A, A)); // compile error 无法展开
| ^
main.c:5:26: note: in definition of macro ‘CONS’
5 | #define CONS(a,b) (int)(a##e##b) //ps:##放到宏参数后面相当于一个连接 无其他作用
| ^
blog link 各种宏定义用法整理