linux c 常用代码
常用C代码碎片:
1、函数参数接口
typedef int(*pfunc)(int x, int y) //pfunc是带两个参数,返回值为int pfunc handler
2、宏函数、宏字符串连接
#define joiner(param1, param2) param1##param2 #define tostring(param) #param #define UARTHANDLER(NAME) UART_##NAME##_recv_handler #define UARTTASKHANDLER(NAME) RS485_##NAME##_task #define UARTTASKSTRING(NAME) "RS485_"NAME"_task"
3、位赋值操作
typedef struct { u8 lv1:1;//故障等级1 u8类型的低位 u8 lv2:1;//故障等级2 u8 lv3:1;//故障等级3 u8 max_lv:2;//最高故障等级(单个故障) u8 res:3;//保留 u8类型的高位 }SINGLE_FLV_FLAG_BIT;//单个故障等级标志位位域
4、统计二进制数中的个数
int func(int x) { int countx = 0; while(x) { countx++; x = x &(x-1); } return countx; }
5、C++使用extern C的巧妙用法
#ifdef __cplusplus # define MODBUS_BEGIN_DECLS extern "C" { # define MODBUS_END_DECLS } #else # define MODBUS_BEGIN_DECLS # define MODBUS_END_DECLS #endif MODBUS_BEGIN_DECLS MODBUS_END_DECLS
6、字符串接收匹配到对应的字符串
int8_t recv_wait_for_resp(modbus_t *ctx, char *msg, uint16_t len, const char *resp) { uint8_t i=0; int16_t rc; uint8_t resp_len = strlen(resp); uint16_t msg_length = 0; while(1) { rc = ctx->backend->recv(ctx, msg + msg_length, 1); if (rc == 0) { return 0; } msg_length += rc; if(msg[msg_length-1] == resp[i]) { if(i==(resp_len-1)) { return msg_length; } i++; } else if(msg[msg_length-1] == resp[0]) { i=1; } else { i=0; } if(msg_length >= len) { return 0; } } return 0; }
7、字节数据转换为可打印字符串
// 如:{0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01} --> "C8329BFD0E01" // pSrc: 源数据指针 // pDst: 目标字符串指针 // nSrcLength: 源数据长度 // 返回: 目标字符串长度 int gsmBytes2String(const unsigned char* pSrc, char* pDst, int nSrcLength) { const char tab[]="0123456789ABCDEF"; // 0x0-0xf的字符查找表 UINT8 i ; for(i=0; i<nSrcLength; i++) { // 输出低4位 *pDst++ = tab[*pSrc >> 4]; // 输出高4位 *pDst++ = tab[*pSrc & 0x0f]; pSrc++; } // 输出字符串加个结束符 *pDst = '\0'; // 返回目标字符串长度 return nSrcLength * 2; }
8、
// 可打印字符串转换为字节数据
// 如:"C8329BFD0E01" --> {0xC8, 0x32, 0x9B, 0xFD, 0x0E, 0x01}
// pSrc: 源字符串指针 // pDst: 目标数据指针 // nSrcLength: 源字符串长度 // 返回: 目标数据长度 int gsmString2Bytes(const char* pSrc, unsigned char* pDst, int nSrcLength) { int i; for(i=0; i<(nSrcLength+1); i+=2) { // 输出高4位 if(*pSrc>='0' && *pSrc<='9') { *pDst = (*pSrc - '0') << 4; } else { *pDst = (*pSrc - 'A' + 10) << 4; } pSrc++; // 输出低4位 if(*pSrc>='0' && *pSrc<='9') { *pDst |= *pSrc - '0'; } else { *pDst |= *pSrc - 'A' + 10; } pSrc++; pDst++; } // 返回目标数据长度 return nSrcLength; }
9、状态字符串描述与状态值
#define ENUM_ITEM(ITEM) ITEM, #define ENUM_STRING(ITEM) #ITEM, #define KEY_STATUS_ENUM(STATUS) \ STATUS(KS_RELEASE) /*稳定松开状态*/ \ STATUS(KS_PRESS_SHAKE) /*按下抖动状态*/ \ STATUS(KS_PRESS) /*稳定按下状态*/ \ STATUS(KS_RELEASE_SHAKE) /*松开抖动状态*/ \ STATUS(KS_NUM) /*状态总数(无效状态)*/ \ typedefenum { KEY_STATUS_ENUM(ENUM_ITEM) }KEY_STATUS; constchar* key_status_name[] = { KEY_STATUS_ENUM(ENUM_STRING) };
10、/*参考CJson代码有浮点数比较,因为浮点数单独采用==或!=判断是不准的,浮点数本质上是无限接近值,所以要用以下函数去判断比较*/
int compare_double(double a, double b) { double maxVal = fabs(a) > fabs(b) ? fabs(a) : fabs(b); return (fabs(a - b) <= maxVal * DBL_EPSILON); }
11、
计算大于等于 x
的最小的 2 的幂
#define B2(x) ((x) | ((x) >> 1)) #define B4(x) (B2(x) | (B2(x) >> 2)) #define B8(x) (B4(x) | (B4(x) >> 4)) #define B16(x) (B8(x) | (B8(x) >> 8)) #define B32(x) (B16(x) | (B16(x) >> 16)) #define NEXT_POWER_OF_2(x) (B32((x)-1) + 1)