2009-10-20 157 views
1

它是安全的轉換,也就是說,從unsigned char *signed char *(或只是一個char *從無符號轉換爲帶符號的類型安全嗎?

+5

你的意思是安全嗎? – 2009-10-20 03:25:18

+0

清理了一下這個問題,但仍不確定「安全」是什麼意思。 – 2009-10-20 03:34:53

+0

我有一個包含ASCII碼字符的std :: string類型的std :: list,我只是需要將它們轉換爲unsigned char *來完成它們的加密。 – cpx 2009-10-20 03:49:20

回答

2

的訪問被良好定義的,你被允許通過一個指針來訪問一個目的是有符號或無符號類型對應於對象的動態類型(3.10/15)。

此外,signed char保證沒有任何陷阱值,因此無論原始對象是什麼值,都可以安全地通過signed char指針讀取。

當然,您可以期望通過一個指針讀取的值與通過另一個指針讀取的值不同。

編輯:關於sellibitze的評論,這是3.9.1/1說的。

char,signed char和unsigned char佔用相同的存儲量並具有相同的對齊要求(3.9);也就是說,它們具有相同的對象表示。對於字符類型,對象表示的所有位都參與值表示。對於無符號字符類型,值表示的所有可能位模式都表示數字。

所以確實看起來signed char可能有陷阱值。好的趕上!

+0

+1我正要寫類似的東西。關於陷阱表示的 – sellibitze 2009-10-20 07:40:04

+0

:我認爲這個保證只適用於無符號字符。至少這是Jack Klein在這裏寫的:http://home.att.net/~jackklein/c/inttypes.html。你能否指出標準中提到的部分? – sellibitze 2009-10-20 07:52:58

+0

該標準允許使用'char'左值讀取任何POD對象(包括無符號字符)。更多 - 它保證當你將這些'char'值寫回同一個'POD'對象時,你會收到原始值。我很難想象如何使用具有陷阱表示的'char'。有任何想法嗎? – 2009-10-20 14:18:21

1

轉換應該是安全的,因爲所有你正在做的是從一個類型的角色轉換到另一個,這應該只要知道你的代碼在你解引用指針時需要什麼類型的數據,因爲這兩種數據類型的數字範圍是不同的(也就是說,如果指針指向的數字原本是無符號的正數,它可能會成爲一個負數,一旦指針轉換爲帶符號的char *並將其解引用)

+0

是的,unsigned char *和signed char *的範圍是不同的。我想問,轉換背後的原因是什麼? – Raptor 2009-10-20 03:29:12

+0

應該問問那個問qn的人嗎?如果char *指向數據,技術上應該是安全的。 – futureelite7 2009-10-20 03:32:03

0

這取決於您將如何使用指針,只是將指針類型。

0

您可以安全地轉換的unsigned char*char *爲您呼叫將被期待從一個字符指針行爲的功能,但是,如果你的char值越過127,那麼你會得到不會是你的結果預計,所以只要確保你的無符號數組對簽名數組有效即可。

0

我已經看到它在幾個方面出錯,從無符號字符轉換爲signed char。

一,如果你使用它作爲一個數組的索引,該索引可能會消極。其次,如果輸入到switch語句中,可能會導致負向輸入,這通常是開關不期望的事情。

第三,它有上算術不同行爲右移

int x = ...; 
char c = 128 
unsigned char u = 128 

c >> x; 

具有不同的結果

u >> x; 

因爲前者是符號擴展,而後者則不是。

第四,有符號字符會導致與無符號字符不同的點處發生下溢。

因此常見的溢出檢查,

(c + x > c) 

可能比

(u + x > u) 
+1

將char轉換爲unsigned char和將char *轉換爲unsigned char *是有區別的。這個問題似乎是關於後者。 – sellibitze 2009-10-20 12:04:41

+0

是的,但問題歸結爲unsigned char vs char,因爲指針並沒有真正添加任何問題。 – 2009-10-20 22:50:11

0

安全返回不同的結果,如果你只處理ASCII數據。

1

投射更改類型,但不影響位表示。從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,或二進制1.1億無符號的字符。轉換爲signed char後,值仍然是110000000,但恰好是-64的2s-complement表示形式。有符號數值以二進制補碼錶示形式存儲。

在第二個示例中,我們的無符號初始值(32)小於128,因此它看起來不受轉換影響。二進制表示是00100000,它在二進制補碼錶示中仍然是32。

到「安全地」從鑄無符號字符到符號的字符,保證值小於128。

0

我很驚訝它還沒有被提及:Boost numeric cast應該做的 - 但只對數據當然。

指針總是指針。通過將它們轉換爲不同的類型,您只會改變編譯器解析指向的數據的方式。

相關問題