從Nginx原始碼談大小寫字元轉化的最高效程式碼以及ASCII碼錶的科學
阿新 • • 發佈:2019-01-23
說起大小寫字母轉換,大家很容易想起系統函式是不是,幾乎所有的程式語言都提供了這種轉換函式,但是你有沒有想過這背後是怎麼實現的?
讓你寫怎麼實現?
我們都知道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