1. 程式人生 > >從Nginx原始碼談大小寫字元轉化的最高效程式碼以及ASCII碼錶的科學

從Nginx原始碼談大小寫字元轉化的最高效程式碼以及ASCII碼錶的科學

說起大小寫字母轉換,大家很容易想起系統函式是不是,幾乎所有的程式語言都提供了這種轉換函式,但是你有沒有想過這背後是怎麼實現的?

讓你寫怎麼實現?

我們都知道Nginx是目前用的最多的Http伺服器,那麼他的程式碼相信也是最高效率的,事實也是如此,最起碼我找不到比他的處理方法更好的了,如果你有歡迎告訴我。

nginx原始碼有這樣一段巨集,用來做大小寫字母的轉換:

nginx-1.6.1/src/core/ngx_string.h   47-48行

#define ngx_tolower(c)      (u_char) ((c >= 'A' && c <= 'Z') ? (c | 0x20) : c)
#define ngx_toupper(c)      (u_char) ((c >= 'a' && c <= 'z') ? (c & ~0x20) : c)

很明顯人家用了位運算,但是為什麼這樣就可以呢?

先看AscII碼錶:

我們只關注其中的大寫字母A-Z和小寫字母a-z。

注意到A是65,大Z是90,小a是97。看似不經意之間,不知道有多少人想過沒有,為什麼Z和小a不是連續的?就是說91-96為什麼要摻雜一些其他特殊字元?

其實,這樣完全不是“本來就是這樣”。而是這樣安排是很科學的,見王爽《組合語言》,已經說得很好了:

這樣做的原因就是讓大小寫互相轉換很方便,也就是可以用位運算,如果小a不是97而是91那麼就不好位運算了。

10進位制65的二進位制是01000001

16進位制的0x20的二進位制就是00100000

10進位制的97二進位制就是01100001,所以大寫轉小寫就是需要把01000001與00100000相“或”即可。

小寫轉大寫就是將01100001變為01000001

~0x20就是按位取反,也就是0xdf,二進位制就是11011111,01100001&11011111=01000001

其實可以得出公式:

如果A|B=C   =>   A=C&~B