2014-01-17 27 views
11

爲什麼下使用「字符輸入」允許訪問對象:爲什麼C/C++討厭簽名字符這麼多?

6.5表達式(C)

一個目的應具有其存儲的值僅由具有一項下列類型的左值表達式訪問:

  • 一個字符類型。

但C++只允許焦炭無符號的字符

3.10左值和右值(C++)

如果一個程序試圖通過的其他一個glvalue比以下類型的行爲是未定義的一個訪問對象的存儲值:

  • char或unsigned char類型。

(從C++標準引號)的符號字符憎恨另一部分:(比基類的子對象等)

3.9類型(C++)

對於任何對象可以複製的類型T,不管對象是否保存T類型的有效值,組成對象的基礎字節都可以複製到數組char或unsigned cha r。如果char的數組內容被複制回對象中,則該對象將隨後保持其原始值。

而且從C標準:

6.2.6的存儲在任何其他對象類型的非位字段的對象類型(C)

值交涉包括N× CHAR_BIT位,其中n是該類型對象的大小,以字節爲單位。該值可以複製到unsigned char [n]類型的對象中(例如,通過memcpy);得到的一組字節被稱爲值的對象表示。

我可以看到很多人對計算器說,是因爲無符號的字符是保證沒有填充位的唯一字符類型,但是C99第6.2.6。2整型

符號字符不得有任何填充比特

那麼,什麼是這背後的真正原因?

+5

你能否提供那些引號來自的_location_? –

+2

「仇恨」從何而來?我在這裏沒有看到問題。 –

+1

* signed char不應該有任何填充位* - 您不能引用C標準來覆蓋C++行爲。 – chris

回答

11

這裏是我採取的動機:

在非二進制補碼系統,signed char將不適合用於訪問對象表示。這是因爲有兩個可能的signed char表示具有相同的值(+0和-0),或者一個表示沒有值(陷阱表示)。在這兩種情況下,這都會阻止你做對於對象表示可能做的最有意義的事情。例如,如果您有一個16位無符號整數0x80ff,則其中一個或另一個字節(如signed char)要陷入或比較等於0.

請注意,在這樣的實現中(非雙向 - 補充),普通char需要定義爲一個無符號類型,通過char訪問對象的表示才能正常工作。雖然沒有明確的要求,但我認爲這是來自標準中其他要求的要求。

+1

該標準的作者的哲學似乎是,沒有理由要求*所有*實現做一些事情,如果可能會有一些實現,它會增加成本,同時提供零利益。如果某項功能或保證在某些平臺上有巨大的優勢,但在其他平臺上則不會,但缺乏授權不應妨礙實施在平臺上支持它。當標準強制執行時,實現應該只支持有用的功能和保證的想法似乎主要是21世紀的發明。 – supercat

7

我想你真正要問的是爲什麼signed char被取消了所有規則允許打字到char*作爲一種特殊情況的資格。說實話,我不知道,尤其是因爲—據我可以告訴— signed char不能有填充或者:

[C++11: 3.9.1/1]:[..]一個char,一個signed charunsigned char佔據相同的存儲量並具有相同的對齊要求(3.11);也就是說,它們具有相同的對象表示。對於字符類型,對象表示的所有位都參與值表示。 [..]

Empirical evidence suggests that it's not much more than convention

  • char被看作是ASCII的一個字節;
  • unsigned char被視爲具有任意「二進制」內容的字節;和
  • signed char左搖擺在風中。

對我來說,似乎沒有足夠的理由排除它從這些標準規則,但我真的找不到任何相反的證據。我要把它歸結爲標準措辭中的一個輕微莫名的怪異現象。

(這可能是因爲我們要問的std-discussion名單這件事。)

+1

'char'是任何字符集正在使用的字節;就我所知,該標準並不表示對ASCII碼優先於EBCDIC。 (順便說一下,在基於EBCDIC的系統中,'char'必須是無符號的(假設它是8位)。對於'signed char',它只是一個非常小的有符號整數類型,保證能夠保存-127到+127。 –

+1

@KeithThompson ** - 128 **到+127對不對? –

+0

@Keith:好吧,我想這足夠了,因爲無符號的<->簽名轉換在技術上是實現定義的,或者任何一個方向(我忘記了它),我們通常將這些「二進制」字節解釋爲無符號值。對? –

6

使用字符類型的檢查對象的表徵是一個黑客。然而,這是歷史性的,必須做出一些調整來允許它。

大多數情況下,在編程語言中,我們想要強打字。 float應該作爲float訪問,而不是int。這具有許多好處,包括減少人爲錯誤並實現各種優化。

但是,有時需要訪問或修改對象的字節。在C中,這是通過字符類型完成的。 C++繼續這一傳統,但它通過消除爲這些目的使用signed char而略微改善了這種情況。

理想情況下,創建一個新類型(比如說byte),並且只允許通過此類型字節訪問對象表示可能會更好,因此將常規字符類型分開只能用作普通整數/字符。也許有人認爲現有的代碼太多,使用charunsigned char來支持這種變化。但是,我從來沒有見過用signed char來訪問對象的表示,所以排除它是安全的。

+0

這真的很有希望,但你能解釋_why_'signed char'是不同的嗎? –

+0

請檢查部分** 3.9類型** for C++和** 6.2.6類型的表示** for C.這兩個標準都只提到unsigned char,因此C也不包括signed char。還有一些爲什麼他們都排除純字符 – Ivan

+0

@Ivan:在排除「signed char」時C不是純粹的。 6.5 7允許以「字符類型」訪問對象的表示。 6.5 6允許將對象複製爲「字符類型的數組」。 –