今天看了一眼nginx
的源码,发现里有两个字母大小写转换的宏,乍一看有点不知所云,感觉这种写法有点高级~
#define ngx_tolower(c) (char)((c >= 'A' && c <= 'Z') ? (c | 0x20) : c) #define ngx_toupper(c) (char)((c >= 'a' && c <= 'z') ? (c & ~0x20) : c)
核心的方法是两个位运算
- 大写转小写
c | 0x20
- 小写转大写
c & ~0x20
在C语言里面字符是使用ASCII
码来表示的,比如A
对应的ASCII码是65,a
对应的ASCII码是97,常规的将A
变成a
的方法只需要将A
减去32即可,反之将a
转换成A
只需要加上32即可。
在这里0x20
是16进制数32
,是的,非常巧合,这里也是32。
c | 0x20
是大写转换小写,大写字母的ASCII码会比对应的小写ASCII码要大32,所以这里的c|0x20
本质上是在c
的基础上加上了32。当然这样看起来不是很直观,从二进制的角度看起来就会变得很直观。
1000001 // 65 A 1100001 // 97 a 0100000 // 32 0x20
可以发现,A
和a
的二进制只相差一位,所以只需要改变这一位,就可以完成转换,而32
对应的二进制的1
恰好可以做到这一点。
|
或运算可以把有差别的那一位变成1
&~
与运算加上取反可以把有差别的那一位变成0
如果你对位运算还不是很熟,可以看一下下面这篇推文。