2014-01-17 7 views
11

なぜCは、「文字種」を使用してオブジェクトへのアクセスを可能にするんC/C++が署名済みのcharをあまりにも嫌うのはなぜですか?

6.5式オブジェクトは、その格納された値は、次のタイプoftheつを有する左辺式によってのみアクセスしなければならない

(C) :

  • 文字の種類。

が、C++のみ文字unsigned char型ことができますか?

3.10左辺値と右辺値(C++)

プログラムは、以下のタイプのいずれかの動作は未定義である以外のglvalueを通じてオブジェクトの格納された値にアクセスしようとする場合:

  • charまたはunsigned char型です。

signed char型憎悪(C++標準からの引用)の別の部分:

3.9タイプ(C++)

(基底クラスのサブオブジェクト以外の)任意のオブジェクトについてオブジェクトがT型の有効な値を保持しているかどうかにかかわらず、オブジェクトを構成する基礎をなすバイトは、の文字列またはの符号なしchaの配列にコピーできます。 rの文字列またはの符号なしの文字列の配列の内容がオブジェクトにコピーバックされた場合、オブジェクトは元の値を保持します。

およびC標準から:

6.2.6タイプ(C)他のオブジェクトタイプのオブジェクトは、から成る非ビットフィールドに格納されている

値の表現N× CHAR_BITビット.nはそのタイプのオブジェクトのサイズ(バイト単位)です。値は、タイプの符号なし文字 [n]のオブジェクトにコピーすることができます(たとえば、memcpyによって)。結果のバイトセットは値のオブジェクト表現と呼ばれます。

私はunsigned char型は、パディングビットを持っていないことが保証のみ文字タイプですが、C99セクション6.2.6 ので、それがあると言ってstackoverflowの上で多くの人々を見ることができます。

signed char型は、任意のパディングビット

を持っていないもの

だから何がこの背後にある本当の理由とは?と言う 2つの整数型

+5

引用符が付いている場所を指定できますか? –

+2

"憎しみ"はどこから来たのですか?私はここに質問が表示されません。 –

+1

* signed charにはパディングビットはありません。* - C++の動作をカバーするためにC標準を引用することはできません。 – chris

答えて

11

はモチベーションが私の感想です:

非2の補数システムでは、signed charは、オブジェクトの表現にアクセスするには適していないだろう。これは、同じ値(+0と-0)を持つ2つの表現、または値を持たない表現(トラップ表現)がある可能性があるためです。どちらの場合でも、これにより、オブジェクトの表現で最も意義のあることをすることができなくなります。たとえば、16ビットの符号なし整数0x80ffがある場合、signed charのいずれかの1つのバイトまたは他のバイトは、0に等しいトラップまたは比較のいずれかになります。

このような実装では(non-twos-補間)、平文charは、正しく動作するためには、char経由でオブジェクトの表現にアクセスするための符号なしタイプとして定義する必要があります。明示的な要件はありませんが、私はこれを標準の他の要件から派生した要件と見ています。

+1

標準の作成者の哲学は、ゼロの利益を提供しながらコストを課す実装がいくつかある場合、*すべての実装が何かをすることを強制する理由はないと思われる。ある機能や保証が他のプラットフォームには大きなメリットをもたらすが、他のプラットフォームでは大きなメリットを享受することができない場合、実装が意味のあるプラットフォーム上で実装を妨げてはならない。実装が、標準によって義務付けられているときに有用な機能と保証しかサポートしないという考え方は、主に21世紀の発明と思われます。 – supercat

7

実際にお尋ねしているのは、signed charが特殊なケースとしてタイプ・ペニングを許可するすべてのルールから除外されている理由です。正直に言うと、私は—は、私の知る限り— signed charを言うことができるようにパディングのいずれか持つことができない、特に以来、知らない:

[C++11: 3.9.1/1]:を[..]charsigned char、およびunsigned charを占めます同じ量のストレージと同じアラインメント要件(3.11)。つまり、それらは同じオブジェクト表現を持ちます。文字型の場合、オブジェクト表現のすべてのビットが値表現に参加します。 [..]

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

  • charがASCIIのバイトと見られています。
  • unsigned charは、任意の「バイナリ」コンテンツを持つバイトとして認識されます。
  • signed charは、風に吹かれたままです。私に

、それはこれらの標準ルールから除外する理由のに十分なように見えるしていませんが、私は正直にこれに反する証拠を見つけることができません。私はそれを標準的な言葉遣いの中で穏やかに説明できない奇妙なものにするつもりです。

は(私たちはこのことについて std-discussionリストを依頼する必要があることかもしれません。)

+1

'char'は、使用中の文字セットのバイトです。標準は、私が知る限り、EBCDICに対してASCIIの優先順位を表明していません。 (BTW、EBCDICベースのシステムでは 'char'は8ビットであると仮定して)符号なしでなければなりません。' signed char'は、-127から-127までの値を保持できるように保証された、 +127。 –

+1

@KeithThompson ** - 128 **〜+ 127 right? –

+0

@Keith:符号なし<->符号付き変換は技術的に実装定義であるか、どちらの方向でも(私は忘れています)、これらの "バイナリ"バイトを符号なしの値と解釈するのに十分です。右? –

6

オブジェクトの表現を検査する文字タイプを使用することはハックです。しかし、それは歴史的なものであり、それを可能にするためにいくつかの宿泊施設が作られなければならない。

ほとんどの場合、プログラミング言語では、厳密な型指定が必要です。 floatの何かはfloatとしてアクセスし、intとしてアクセスしないでください。これには、人為的ミスを減らし、さまざまな最適化を可能にするなど、多くの利点があります。

ただし、オブジェクトのバイトにアクセスまたは変更する必要がある場合があります。 Cでは、これは文字の種類によって行われました。 C++はその伝統を継承していますが、これらの目的のためにsigned charの使用を排除することで状況を少し改善します。

新しいタイプ、たとえばbyteを作成し、このタイプでのみオブジェクト表現へのバイトアクセスを許可し、正規の文字タイプを通常の整数/文字としてのみ分離する方が理想的です。おそらく、このような変更をサポートするには、既存のコードがあまりにも多く、charunsigned charを使用していると考えられました。しかし、私はsigned charがオブジェクトの表現にアクセスするのを見たことがないので、除外しても安全でした。ここで

+0

これは本当に有望ですが、「signed char」が違っていることを説明できますか? –

+0

** 3.9タイプ**をC++に、** 6.2.6タイプをCで表す**どちらの規格もここでは符号なしの文字のみを示しているので、Cは符号付きの文字も除外します。そして、どちらも普通の文字を除外します – Ivan

+0

@Ivan:Cは 'signed char'を除いて純粋ではありません。 6.5 7では、「文字型」のオブジェクトの表現にアクセスできます。 6.5 6では、オブジェクトを「文字型の配列」としてコピーすることができます。 –

関連する問題