43

これは推奨される方法(または未定義の動作)の問題ではありませんが、整数型のすべてのバイトをの値に変換することに関して、 c++(unsigned char)0標準が実際に保証することについてです。


質問)

以下のスニペットでは、ifステートメントで使用される式はtrueと評価されることが保証されていますか?

std::memset (
  reinterpret_cast<char*> (&a), // int a;
  (unsigned char)0,
  sizeof (int)
);

if (a == 0) {
  ...
}

C99およびC++11標準(この投稿のさらに下)からの引用を読むことにより、C99は、すべてのビットが設定された整数型がその型の値を表すことを明示的に保証していることがわかります。00

この保証はC++11標準では見つかりません。

  • そのような保証はありませんか?
  • 前のスニペットの結果は本当に実装固有ですか?


C99(ISO / IEC 9899:1999)

5.2.1.2/1マルチバイト文字

すべてのビットがゼロのバイトは、シフト状態に関係なくヌル文字として解釈されます。このようなバイトは、他のマルチバイト文字の一部としては発生しません。

6.2.6.2/1整数型

パディングビットの値は指定されていません。45)符号ビットがゼロである符号付き整数型の有効な(非トラップ)オブジェクト表現は、対応する符号なし型の有効なオブジェクト表現であり、同じ値を表すものとします。

任意の整数型の場合、すべてのビットがゼロであるオブジェクト表現は、その型の値ゼロの表現でなければなりません。



C ++ 11の場合(ISO / IEC 14882:2011)

2.3/3文字セット[lex.charset]

基本実行文字セットと基本実行ワイド文字セットには、それぞれ、基本ソース文字セットのすべてのメンバーに加えて、アラート、バックスペース、およびキャリッジリターンを表す制御文字に加えて、ヌル文字(それぞれヌルワイド文字)が含まれます。その表現はすべてゼロビットです。

4

4 に答える 4

14

C++ 11

該当する部分は

3.9.1/1 C++11 の場合

文字型の場合、オブジェクト表現のすべてのビットが値表現に関与します。符号なし文字タイプの場合、値表現の可能なすべてのビット パターンは数値を表します。これらの要件は、他のタイプには当てはまりません。

3.9.1/7に伴い

整数型の表現は、純粋な 2 進表記法を使用して値を定義する必要があります。

C11

6.2.6.2 は非常に明示的です

unsigned char 以外の unsigned 整数型の場合、オブジェクト表現のビットは、値ビットとパディング ビットの 2 つのグループに分けられます (後者のいずれかが存在する必要はありません)。N 個の値ビットがある場合、各ビットは 1 ~ 2 N-1の間の異なる 2 のべき乗を表すため、その型のオブジェクトは純粋な 2 進数表現を使用して0 ~ 2 N − 1の値を表すことができます。これは、値表現として知られるものとします。パディング ビットの値は指定されていません。

符号付き整数型の場合、オブジェクト表現のビットは、値ビット、パディング ビット、符号ビットの 3 つのグループに分けられます。パディング ビットは必要ありません。signed char にはパディング ビットがあってはなりません。正確に 1 つの符号ビットがあります。値ビットである各ビットは、対応する符号なし型のオブジェクト表現の同じビットと同じ値を持つものとします (符号付き型に M 個の値ビットがあり、符号なし型に N 個の値ビットがある場合、M ≤ N)。符号ビットがゼロの場合、結果の値には影響しません。符号ビットが 1 の場合、値は次のいずれかの方法で変更されます。

— 符号ビット 0 の対応する値は否定されます (符号と大きさ)。

— 符号ビットの値は -(2 M ) (2 の補数) です。

— 符号ビットの値は -(2 M − 1 ) (1 の補数) です。

これらのうちどれが適用されるかは実装定義であり、符号ビットが 1 ですべての値ビットが 0 (最初の 2 つの場合) の値、または符号ビットとすべての値ビットが 1 (1 の補数の場合) の値がトラップ表現であるかどうかと同様です。または正常値。符号と大きさと 1 の補数の場合、この表現が正常な値であれば、負のゼロと呼ばれます。

まとめ

どちらの規格も意図は同じだと思います。

  • char、すべてのビットが値に参加signed charするunsigned char

  • 他の整数型には、値に関与しないパディング ビットがある場合があります。それらの間違ったビット パターンは、無効な値を意味する場合があります。

  • 解釈は純粋なバイナリ表現であり、その定義は上記の C11 の引用で拡張されています。

明確でない可能性のある2つのこと:

  • -0 (符号と大きさ、および _ones の補数) は C++ のトラップ値にすることができます

  • パディング ビットの 1 つをパリティ ビットにすることはできますか (つまり、パディング ビットが変更されていないことを確認した場合、表現を変更できますか)

私は保守的で、どちらもイエスだと思います。

于 2012-06-21T14:02:32.813 に答える
2

はい、保証されています。

整数型のすべてのバイト/ビットを回転させると0、前述の標準の以下のスニペットで示されているように、型のインスタンスの値がゼロ()になることが保証されます。


3.9.1/7基本タイプ

整数型の同義語は整数型です。整数型の表現は、純粋な2進記数法を使用して値を定義するものとします。49

49 2進数の0と1を使用する整数の位置表現。連続するビットで表される値は加算され、1で始まり、2の連続する整数乗が乗算されます。ただし、おそらく最も高い位置にあるビットは除きます。(情報処理システムのためのアメリカ国立辞書から適応。)

于 2012-06-21T12:30:01.163 に答える
2

いいえ。たとえば、標準にはバイアスに基づく表現を禁止するものは何もなく、それがバイナリであることを義務付けているだけです。

于 2013-02-23T21:25:11.933 に答える
1

いいえ、実際に保証されているとは思いませんが、あいまいです。

all-bits-zero がの表現ではないC++ 実装があったとしたら、私は非常に驚かれることでしょう。0

C99標準について考えることから始めましょう。(はい、わかっています。質問は C++ に関するものです。ご容赦ください。) 符号なし整数型のオブジェクト表現のビットは、値ビットとパディング ビットの 2 つのグループに分けられると書かれています (パディングは必要ありません)。ビット、およびほとんどの実装にはそれらがありません)。値のビットは、純粋なバイナリ表現を構成します。パディング ビットは値に影響しません。パディング ビットの組み合わせによっては、トラップ表現が生成される場合があります。

符号付きの型は似ていますが、符号ビットが 1 つ追加されています。符号付きの型は、符号と大きさ2 の補数、または1 の補数のいずれかを使用して表すことができます。ただし、パディング ビットは値に寄与せず、パディング ビットの組み合わせによってはトラップ表現が生成される場合があります。

この説明は、たとえば、より幅の広い整数型char が常に 1 でなければならない単一のパディング ビットを持つ可能性を排除するものではありません。0 の場合、トラップ表現があります。または、おそらくよりもっともらしく、奇数のパリティビットを持っている可能性があります。

C99 標準が発行された後、2 番目の Technical Corrigendum に次の文が追加されました。これは C11 にも表示されます。

任意の整数型の場合、すべてのビットがゼロであるオブジェクト表現は、その型の値ゼロの表現でなければなりません。

これは、脚注としてではなく、規範的なテキストとして追加されたことを強調しておきます。これは、委員会のメンバーが、保証が C99 標準にまだ暗示されていないと感じていたことを示唆しています (ただし、証明はしていません)。

(C90 は、整数型がどのように表現されるかについてはるかに具体的ではありませんでした。パディング ビット、トラップ表現、または 2 の補数などについては言及されていませんでした。少なくとも C99 と同じくらいの柔軟性が実装に与えられたと私は主張します。)

そのため、C99 TC2 以降、C 言語は、すべてのビットがゼロであることが、任意の整数型のゼロの表現であることを保証します。C99 と C90 では、その保証は述べられていません。

それは C です。C++ はどうでしょうか。

2011 C++ 標準は、古い 1990 C 標準よりも、整数型の表現についてわずかに特異性を高めているようです。符号付き型は、2 の補数、1 の補数、または符号付きマグニチュードのいずれかを使用して表現する必要があります。また、「純粋な 2 進数システム」も必要です。「トラップ表現」については言及しておらず、ビットフィールドのコンテキストを除いてパディングビットについても議論していません。

そのため、C90 と TC2 以前の C99 の両方で、少なくとも理論的には、全ビット ゼロが整数型のトラップ表現になる可能性がありました。整数型に対する C++ 標準の要件は、C90 および C99 の要件と非常によく似ています。「純粋なバイナリ表現」が必要ですが、それは C99 の場合と同様に、値ビットにのみ適用されると主張します。C++ はパディング ビットについて言及していませんが、禁止していません。

繰り返しますが、これは主に理論的な関心事です (したがって、「言語弁護士」タグ)。C 委員会は、すべての実装が既にそれを満たしているため、全ビット ゼロがゼロの表現でなければならないという要件を自由に課すことができました。同じことがほぼ間違いなく C++ にも当てはまります。

于 2013-06-22T06:51:46.057 に答える