见过代码中出现两个感叹号吗?

9598f74349dc4cbbace81bee87638385.png

今天继续更新一篇小短文,希望对你有帮助。

int func(int temp)
{
  return !!temp;
}

不知道你是否看过上面类似的代码,两个感叹号出现在代码中,难道代码也有思想,也需要表达情感吗?

刚学习 C语言的时候,你应该经常看到过 1 个感叹号的情况,比如:

if(one != two)
{
  .......
}
-----------------------------------------
if(!temp)
{
......
}
-----------------------------------
typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
-----------------------------------------
one = !temp;

但两个感叹号估计就很难见到了。

鱼鹰大学四年、工作三年都没见过这种写法,直到前段时间看 Linux 源码,才接触到,第一次看到时非常惊讶,怎么还有这种写法?

为什么要用两个感叹号,作用是什么,只是为了表现 C 语言的奇技淫巧吗?

仔细想过后才惊叹其中的巧妙。

假设一个字节变量 byte,可代表范围 0~255,0 代表其中一种含义,1 ~255 代表另一种含义(你可能会问,怎么不直接用 0 和 1 表示,因为这个变量本身不只有 0 和 1,只是在另一个使用的地方才会只使用二值含义,总之会有这种情况)。

如果我要用另一个变量 bit 来表示这两种含义,一般情况我们会这么做:

int func(unsigned char byte)
{
unsigned char bit;


  if(byte == 0)  {
    bit = 0;
  }
  else{
bit = 1;
  }
  return bit;
}

更优雅简单一点是这样写:

int func(unsigned char byte)
{
  bit = byte ? 1 : 0;
return bit;
}

但不管哪一个,都不如第一个简单高效。

简单可以很容易看出来,高效何在?

它不需要判断语句(判断语句在单片机中可能影响不是很大,但在有多级缓存的情况下,影响可能很大,这就是为什么 linux 中用 likely() 之类的进行优化)。

这样,不管原先的 byte 是什么值,都将变成 0 或 1

这样一来,如果调用者使用如下方式:

if(func() == 1)
{
  
}
或者 
if(func())
{


}

 都不会出现问题。

对于负数也是如此,只要是为了把 0 单独分开,都可以采用这种方式。

这在底层开发中也非常实用。

比如 GPIO 有个引脚号需要判断是 0 或 1,一般这样:

bit =  (GPIOB->IDR & GPIO_Pin_4) >> 4;


或者
bit = (GPIOB->IDR & GPIO_Pin_4) ? 1 : 0;

上一种确实也是不错的选择,但是这里需要修改两个地方,修改时很容易遗忘,所以不如下面这种简单:

bit =  !!(GPIOB->IDR & GPIO_Pin_4);

如果换个 IO ,需要修改代码时,只要修改一次就搞定,相当方便,所以建议大家使用上面那种方式获取位的值。

而从汇编的角度来看,两次 ! 也只需要一条指令搞定:

95eeb8d47e2e6f962dcce0219a96ec2c.png

效率不输移位方式!

37f48c3f899bc2bbce50ff4a60db0251.png

1.嵌入式还有哪些风口值得入?

2.STM32和Arduino对比,谁更厉害?

3.嵌入式模块化编程、驱动分离的重要性

4.用CH573实现自拍杆蓝牙遥控器

5.带你一步一步理解C语言指针!

6.欧洲处理器项目第一阶段完成:29个RISC-V内核

c724145717f48005d2c202182da7e93d.gif

免责声明:本文系网络转载,版权归原作者所有。如涉及作品版权问题,请与我们联系,我们将根据您提供的版权证明材料确认版权并支付稿酬或者删除内容。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值