C 语言学习(3)---- C语言中的位运算和宏定义

1.常用的位运算操作

设置/清零、取反某些位

对某一位置 1,需要用和 1 按位或的方法;

对某一位置 0,需要用和 0 按位与的方法;

对某一位翻转,需要用和 1 按位异或的方法;

使用宏定义实现的方法如下:

#define setbit(x,y) x |= (1 << y)

#define clrbit(x,y) x &= ~(1 << y) 

#define reversebit(x,y) x ^= (1 << y )

对齐操作

一般对于存储内存地址的变量,需要做内存对齐操作,对齐数量通常都是 2 的倍数,比如 2/4/8/16 位对齐,相对应的二级制是 10(BIN),100(BIN),1000(BIN),10000(BIN);所以对齐的方式是对最后几位二进制位直接置 0 实现是向后对齐,向前对齐是在 value 上加上 base -1 的值

使用宏定义的实现方法如下:

// align back remove tail
#define tAlign(value, base)  value & ~(base - 1)

// align front add forward
#define sAlign(value, base)  ((value) + (base - 1))/(base) * base

// align front add forward
#define mAlign(value, base)  ((value)+ (base - 1) & (~(base - 1)))

取出特定的位

对于一个 int 类型 4字节的整型数,按照 8bit 的方式获取高低位的方法如下:

uint32_t temp = 0x12345678;
printf("test get bits demo \n");
printf("31 ~ 24bits %x \n", (temp & (0xff << 24)) >> 24);
printf("24 ~ 16bits %x \n", (temp & (0xff << 16)) >> 16);
printf("16 ~ 8bits %x \n", (temp & (0xff << 8)) >> 8);
printf("8 ~ 0bits %x \n", (temp & (0xff << 0)) >> 0);

也可以使用下面的宏:

#define BIT_M_TO_N(x, m, n) ((unsigned int)(x << (31-(n))) >> ((31 - (n)) + (m)))

//BIT_M_TO_N(x, 0, 7)  ((unsigned int)(x << (31 - (7))) >> ((31 - (7)) + (0)))
//BIT_M_TO_N(x, 0, 7)  ((unsigned int)(x << 24) >> ((24) + (0)))

先左移特定的位数,低位补0,默认是无符号类型,所以再进行逻辑右移,将低位的值丢弃,这个宏有一般性,可以获取任意的 [m,n]  m ~n 连续 的数值:

printf("%x \n", BIT_M_TO_N(0x12345678, 0, 7));
printf("%x \n", BIT_M_TO_N(0x12345678, 8, 15));
printf("%x \n", BIT_M_TO_N(0x12345678, 16, 23));
printf("%x \n", BIT_M_TO_N(0x12345678, 24, 31));

对特定的字节清零

#define CLEAR_LOW_BYTE0(x) (x &= 0xffffff00)  /* 清零第0个字节 */
#define CLEAR_LOW_BYTE1(x) (x &= 0xffff00ff)  /* 清零第1个字节 */
#define CLEAR_LOW_BYTE2(x) (x &= 0xff00ffff)  /* 清零第2个字节 */
#define CLEAR_LOW_BYTE3(x) (x &= 0x00ffffff)  /* 清零第3个字节 */

#define  SET_LOW_BYTE0(x)    (x |= 0x000000ff)    /* 第0个字节置1 */    
#define  SET_LOW_BYTE1(x)    (x |= 0x0000ff00)    /* 第1个字节置1 */    
#define  SET_LOW_BYTE2(x)    (x |= 0x00ff0000)    /* 第2个字节置1 */    
#define  SET_LOW_BYTE3(x)    (x |= 0xff000000)    /* 第3个字节置1 */

2.常用的宏的使用方法

使用 # 将标志符转换为字符串

//  标记前使用“#”特殊符号将其转换为字符串的标记
#define TOSTR(n) #n

printf("tostring %s \n", TOSTR(hello));

int var_a = 100;
printf("%s = %d \n", TOSTR(var_a), var_a);

使用##将两个标志符以字符串的方式连接

//## 用于将两个标志符用字符串的方式连接
#define CONNECT(a, b) a##b
const char *pstr = "Follow your heart";
printf("%s = %s\n", TOSTR(ptr), pstr);

printf("connect a b %d \n", CONNECT(var, _a));

const char *p = "hello world";
CONNECT(debug, Printf)("%s \n", p); // using connect as function name 

可变参数宏的定义

使用 ##__VA_ARGS__ 表示是传入的可变参数,跟前面的 字符串类型的 fmt 配合,将可变参数传递到另一个支持可变参数的函数上

#define DBGPRINT(fmt, ...) printf("DEBUG:[%s] line:%d " fmt, __FUNCTION__, __LINE__, ##__VA_ARGS__);

DBGPRINT("demo printf %s var_a = %d\n", p, var_a);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值