簡體   English   中英

從無簽名轉換為簽名類型安全?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM