2012-09-24 57 views
1

將鑄件解決下面的警告是否安全,或者我可以簡單地改變原型來返回u_char而不是?將鑄造一個char/unsigned char是否安全?

警告:返回 'u_char [256]' 從與結果類型的函數 '的char *' 指針爲整數類型的具有不同符號之間轉換[-Wpointer-SIGN]

char * whatever(unsigned char *text) 
{ 
     static u_char retval[256]; 
     int pos = 0; 

     *retval = 0; 
     if (!text) 
       return retval; 

     for (; *text && (pos < 254); text++, pos++) { 
       if (*text < 32) { 
         retval[pos++] = '^'; 
         retval[pos] = *text + 64; 
       } else if (*text == 127) { 
         retval[pos++] = '^'; 
         retval[pos] = '?'; 
       } else 
         retval[pos] = *text; 
     } 

     retval[pos] = 0; 
     return retval; 
} 

我也可以接受其他可能性。

回答

2

當然你應該改變返回類型,如果你認爲數據是無符號的。

一般來說,你的代碼有點嚇人,因爲它似乎是根據ASCII值硬編碼有關字符的假設。這不是我推薦做的事情,請看isprint()功能和朋友檢查角色的便攜方式。文本通常假定爲const char *,而不是const unsigned char *

最後,當然返回一個指向static緩衝區的指針也會有點危險,代碼不是線程安全的,並且如果多次調用完成,很難在外部跟蹤返回值並實現它被隨後的調用覆蓋。

+0

我敢說每個人*都會假設文本是'const unsigned char *'。對於很多人來說,差異並不重要,只要手中的實現將'char'視爲簽名而不是無符號類型即可。 –

1

因爲你的函數使用輸入的unsigned char*,似乎有理由爲它的輸出返回unsigned char*,除非功能的預期目的部分是轉換從unsigned charchar。如果這是目的的一部分,那麼retval應該是一個char的數組,而不是數組u_char

unsigned char轉換爲char很可能是2補碼實現(幾乎所有這些)的無操作。但實際上並沒有保證,即使是2的補碼。對於大於CHAR_MAX(通常爲127)的值,允許轉換改變位模式或者甚至提高信號。在從unsigned char轉換爲char不是的實施方案中,沒有任何操作(大約沒有任何操作),從unsigned char*轉換爲char*是不安全的,因此警告。

所以實際上,這個警告告訴你需要決定(和記錄)你的函數處理什麼類型的字符。不要避免使用一個強制轉換的決定。

0

有數百萬行代碼將char*unsigned char*視爲可互換,而C標準並未要求它們可互換。是否「安全」取決於您所說的單詞的含義......如果您認爲您可能將代碼移植到當前不存在的不兼容的兼容實現中,或者如果您訂閱書面說,任何不符合C標準的東西都可能會擦掉硬盤。

但是,編寫正確的類型安全代碼要好得多,在這種情況下甚至不會出現問題。換句話說,不要避免演員因爲它是「不安全的」,避免演員因爲它是不好的編碼練習。部分糟糕的是,任何演員都可以隱藏bug ...舉個例子,假設你認爲char*unsigned char*實際上是一些其他類型,比如intint* ......你剛剛阻止了編譯器告訴你它。類型和類型安全性是通過在編譯時儘早捕獲錯誤來避免錯誤的強大工具。