C 語言的 switch 語句很是強大。然而,它不能用字符串做爲判斷條件,只能用常整數。這是能夠理解的,由於 C 的字符串僅僅是數組,它們並非並非一個總體。javascript
在某些狀況下,將 string 做爲 switch 語句判斷條件是很是有用的。在 lwan 中我用一個小竅門避免在熱門路徑調用 strcmp 家族函數。這是利用字符串僅僅是字節數組這個概念,咱們將這些字節數組轉化成一個指向 32 位整數的指針,並解引用這個指針。利用這個竅門,咱們就能夠在 switch 語句中使用短小的字符串(例如:文件擴展名,包括 . 它們大多數只有四個字符)來做爲判斷條件。css
C 也支持多字節整型常量。然而因爲大小端的影響, 當你在這些編譯這些常量時啓用 -Wall -Wextra 選項,GCC 會發出警告。個人解決方法是:用宏和枚舉類型配合去建立一個編譯器指望的常整型。下面的代碼直接從 lwan 拷貝的,爲了說明 STRING_SWITCH 語句的用法:html
1 #define STRING_SWITCH_L(s) switch (*((int32_t *)(s)) | 0x20202020) 2 #define MULTICHAR_CONSTANT(a,b,c,d) ((int32_t)((a) | (b) << 8 | (c)<< 16 | (d) << 24)) 3 4 enum { 5 EXT_JPG = MULTICHAR_CONSTANT_L('.','j','p','g'), 6 EXT_PNG = MULTICHAR_CONSTANT_L('.','p','n','g'), 7 EXT_HTM = MULTICHAR_CONSTANT_L('.','h','t','m'), 8 EXT_CSS = MULTICHAR_CONSTANT_L('.','c','s','s'), 9 EXT_TXT = MULTICHAR_CONSTANT_L('.','t','x','t'), 10 EXT_JS = MULTICHAR_CONSTANT_L('.','j','s',0), 11 } lwan_mime_ext_t; 12 13 const char* lwan_determine_mime_type_for_file_name(char *file_name) 14 { 15 char *last_dot = strrchr(file_name, '.'); 16 if (UNLIKELY(!last_dot)) 17 goto fallback; 18 19 STRING_SWITCH_L(last_dot) { 20 case EXT_CSS: return "text/css"; 21 case EXT_HTM: return "text/html"; 22 case EXT_JPG: return "image/jpeg"; 23 case EXT_JS: return "application/javascript"; 24 case EXT_PNG: return "image/png"; 25 case EXT_TXT: return "text/plain"; 26 } 27 28 fallback: 29 return "application/octet-stream"; 30 }
咱們注意到,STRING_SWITCH_L 是將字符串與一個 32 位整數按位或,這樣作能夠一次性檢測 4 個字符的狀況。java
這樣的 switch 語句在 lwan 中用來匹配 HTTP 頭和 HTTP 請求方法。也用來作簡單的文件擴展名到 MIME-Type 的轉換,就像上面代碼所展現的那樣。數組
譯自 http://tia.mat.br/blog/html/2012/08/09/string_switch_in_c.html ,若有錯誤,清留言!app