[英]Conversion from unsigned to signed type safety?
例如,從unsigned char *
為帶signed char *
(或只是char *
?)是否安全?
訪問是明確定義的,允許您通過指向對應動態類型(3.10 / 15)的有符號或無符號類型的指針來訪問對象。
此外,保證signed char
不具有任何陷阱值,因此無論原始unsigned char
對象的值是什么,您都可以安全地讀取signed char
指針。
當然,您可以期望通過一個指針讀取的值與通過另一個指針讀取的值不同。
編輯:關於sellibitze的評論,這是3.9.1 / 1所說的。
char,signed char和unsigned char占用相同的存儲空間並具有相同的對齊要求(3.9); 也就是說,它們具有相同的對象表示。 對於字符類型,對象表示的所有位都參與值表示。 對於無符號字符類型,值表示的所有可能位模式表示數字。
事實上,似乎signed char
可能有陷阱值。 好抓!
轉換應該是安全的,因為你所做的只是將一種類型的字符轉換為另一種字符,它應該具有相同的大小。 只需要知道在取消引用指針時代碼所期望的數據類型,因為兩種數據類型的數值范圍不同。 (即,如果指針指向的數字原來是正數為無符號,則一旦指針轉換為帶符號的字符*,它就可能成為負數,並取消引用它。)
轉換會更改類型,但不會影響位表示。 從unsigned char轉換為signed char不會更改值,但會影響值的含義。
這是一個例子:
#include <stdio.h>
int main(int args, char** argv) {
/* example 1 */
unsigned char a_unsigned_char = 192;
signed char b_signed_char = b_unsigned_char;
printf("%d, %d\n", a_signed_char, a_unsigned_char); //192, -64
/* example 2 */
unsigned char b_unsigned_char = 32;
signed char a_signed_char = a_unsigned_char;
printf("%d, %d\n", b_signed_char, b_unsigned_char); //32, 32
return 0;
}
在第一個示例中,您有一個值為192的unsigned char,或二進制的110000000。 在轉換為signed char之后,該值仍然是110000000,但這恰好是-64的2s補碼表示。 有符號值以2s-補碼表示形式存儲。
在第二個示例中,我們的無符號初始值(32)小於128,因此它似乎不受強制轉換的影響。 二進制表示為00100000,其仍為32s的2s補碼表示。
要“安全地”從unsigned char轉換為signed char,請確保該值小於128。
這取決於你將如何使用指針。 您只是轉換指針類型。
您可以將安全地轉換unsigned char*
的char *
為您呼叫將被期待從一個字符指針行為的功能,但是,如果你的char值越過127,那么你會得到不會是你所預期的結果,所以請確保您的無符號數組中的內容對有符號數組有效。
我已經看到它在某些方面出錯了,從unsigned char轉換為signed char。
其一,如果你將它用作數組的索引,該索引可能會變為負數。
其次,如果輸入到switch語句,則可能導致負輸入,這通常是交換機不期望的。
第三,它在算術右移上有不同的行為
int x = ...;
char c = 128
unsigned char u = 128
c >> x;
有不同的結果
u >> x;
因為前者是符號擴展而后者不符號。
第四,有符號字符會導致與無符號字符不同的點下溢。
所以常見的溢出檢查,
(c + x > c)
可能會返回不同的結果
(u + x > u)
如果您只處理ASCII數據,則安全。
我很驚訝它還沒有被提及: Boost數字演員應該做的伎倆 - 當然只針對數據。
指針總是指針。 通過將它們轉換為其他類型,您只需更改編譯器解釋指向的數據的方式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.