2012-06-20 43 views
0

這段代碼我在看有很多,我看到這樣的事情發生的地方:
將一個無符號變量賦值給一個有符號值的處理是什麼?

char *functionName(char *passedVariable) 
{ 
    unsigned char *newVariable = (char*) passedVariable; 

爲什麼能這樣做?我總是試圖在使用簽名/未簽名方面保持一致,因爲我知道兩者之間的切換會導致問題,但這位開發人員似乎並不在乎。

回答

1

更改指針類型並不是真正的問題,該地址仍然有效。 但是,如果且僅當...簽名數據爲負數,才能將指出的數據解釋爲有符號/無符號。所以在你的例子中,如果你的char總是正面的,那麼沒關係,否則它不是。符號/無符號鑄件

實施例:

char c = 42; 
char d = -42; 
unsigned char cu = c; 
unsigned char du = d; 

printf("c %d\n", c); 
printf("cu %d\n", cu); 
printf("d %d\n", d); 
printf("du %d\n", du); 

輸出:

c 42 
cu 42 
d -42 
du 214 
+0

這很酷。感謝您向我展示每個結果。我知道在C中更改變量的簽名性可能會非常棘手,並且以這種方式說明它的含義非常有幫助! – petFoo

0

它們可能是例如UTF-8字符串,它由無符號字節組成,可能需要手動處理,但它們可以安全地傳遞給printf,在許多平臺上它們都需要一個帶符號的字符,所以你有投到某處以避免警告。

+0

請問您能詳細說明一下嗎?我不完全明白你在說什麼。 – petFoo

+0

如果您手動檢查UTF-8字符串長度,例如,有一些按位操作處理無符號字符。另一方面,要將字符串打印到啓用了Unicode的控制檯,您可以使用printf。 Printf期望一個普通的「char *」,它通常轉換爲「signed char *」。因此,要麼必須強制轉換字符串以獲取其長度或打印它們,兩種操作通常都無法用相同類型的指針完成,即使該強制轉換實際上並不會實際改變任何操作,而只是一些按位操作語義。 – jjrv

0

在字符串的情況下,您的示例看起來像,它可能沒有關係。 ASCII值只能從0-127變化,這意味着它們可以適應無符號字符或無符號字符而沒有問題。另外,未修飾的char的簽名是實現定義的(因此存在signed關鍵字)。如果char是無符號類型,則您的示例根本沒有任何符號轉換。

通常,在使用不同編碼風格的第三方代碼或對char的簽名做出不同假設時,示例中的投射類型用於關閉「指示標誌」警告。在這種情況下保持一致並不總是可能的,但通過投射來改變字符串指針的符號不會導致任何問題。

+1

但是所顯示的模型不會使任何警告消失。 –

+0

「它可能沒關係」 - 使用'unsigned char *'的常見原因是使用需要無符號char值(或EOF)的ctype.h函數;那麼它確實很重要。 –

+0

@HotLicks確實如此。我只注意到這行代碼,因爲我的編譯器給出了一個警告。它和整個警告頁面。 – petFoo

0

對於一個指針,它並不重要,只要有符號和無符號的字符在內存中的大小相同,這就是地址。並且無符號字符*對於任意內存地址最有意義 - 這就是爲什麼大多數純粹的內存函數將其作爲一個爭論點

0

不是由C語言指定的char的符號性是因爲字符不是通過自然帶符號的值,並且當C被標準化時,有些實現將它們視爲已簽名,有些則沒有。因此,將char轉換爲signed charunsigned char總是安全的。前者不常見,但後者是爲了將char用作數組索引或ctype.h is...to...函數的參數。但是沒有看到使用unsigned char*指針的任何實際代碼,因此不可能確定它爲什麼被使用。

+0

在這個特定的例子中,它看起來好像他沒有使用變量來聲明任何重要的東西。他在if語句中使用它,但if語句沒有做任何事情。它只有一個註釋,說它需要更好的錯誤處理。但這不是他在這個項目中唯一做到的地方。 – petFoo

相關問題