七年了,没见过代码中出现过两个感叹号

开发 前端
为什么要用两个感叹号,作用是什么,只是为了表现 C 语言的奇技淫巧吗?仔细想过后才惊叹其中的巧妙。

有半个多月没更新笔记了,广告少,动力也明显不足了,挺安逸的,毕竟最近鱼鹰也有其它事情要忙,主业要紧。在此感谢大家的继续关注!

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

  1. int func(int temp
  2.   return !!temp

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

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

  1. if(one != two) 
  2.   ....... 
  3. ----------------------------------------- 
  4. if(!temp
  5. ...... 
  6. ----------------------------------- 
  7. typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus; 
  8. ----------------------------------------- 
  9. one = !temp

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

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

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

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

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

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

  1. int func(unsigned char byte) 
  2.   unsigned char bit
  3.    
  4.   if(byte == 0)  { 
  5.     bit = 0; 
  6.   } 
  7.   else
  8.     bit = 1; 
  9.   } 
  10.   return bit

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

  1. int func(unsigned char byte) 
  2.   bit = byte ? 1 : 0; 
  3.   return bit

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

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

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

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

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

  1. if(func() == 1) 
  2.    
  3. 或者  
  4. if(func()) 
  5.    

都不会出现问题。

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

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

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

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

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

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

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

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

 

效率不输移位方式!

 

责任编辑:武晓燕 来源: 鱼鹰谈单片机
相关推荐

2015-06-19 11:00:09

bash

2020-12-24 10:40:44

Linux命令文件

2020-08-13 09:35:50

Linux命令软件

2022-04-26 09:01:45

运算符TypeScript代码

2021-12-19 13:41:46

WiFi电脑技术

2019-07-19 09:24:35

Java开发代码

2023-12-10 14:28:58

VS Code软件开发代码编辑器

2016-06-22 10:18:59

联想服务器

2022-04-22 10:41:53

HTML标签功能

2022-09-26 19:20:07

CSS选择器HTML

2017-12-19 15:17:18

OpenStackEasyStack

2020-03-08 17:20:21

微信互联网封链

2022-02-16 09:54:43

AI模型

2012-07-18 09:43:40

FLash

2015-11-23 09:52:02

2022-07-29 12:04:04

GitHub开源神器

2023-07-28 07:43:55

2022-03-21 08:40:32

开源VsCode编辑器

2023-01-12 22:06:52

JVMGraalVMSpring

2011-08-10 08:24:39

项目经理
点赞
收藏

51CTO技术栈公众号