1

このコードの結果が にならないのはなぜy == 0x100ですか?

uint8_t x = 0xff;
unsigned y = ++((unsigned)x);

こちらでご確認ください: http://codepad.org/dmsmrtsg

4

4 に答える 4

9

あなたが投稿したコードは、C 言語の観点からは無効です。C でのキャストの結果は右辺値です。の引数としては使用できません++。演算子++には左辺値引数が必要です。つまり、式++((unsigned) x)は標準 C 言語ではコンパイルできません。

この場合に実際に観察されるのは、GCC の「一般化された左辺値」拡張です。

http://gcc.gnu.org/onlinedocs/gcc-3.4.4/gcc/Lvalues.html

その拡張に従って (標準 C とは逆に)、左辺値に適用されたキャストは左辺値を生成します。結果の「一般化された」左辺値に何かを書き込もうとすると、書き込まれる値が2 回変換されます。最初に明示的なキャストによって指定された型に変換され、次に中間結果が受信者オブジェクトの型に再度変換されます。最終結果は受信者オブジェクトに配置されます。

たとえば、あなたのx場合

(unsigned) x = 0x100;

実際にはGCCによって次のように解釈されます

x = (uint8_t) (unsigned) 0x100;

の最終値はxになります0

そして、これはまさにあなたの例で起こっていることです。GCC では、

++((unsigned) x)

と同等です

(unsigned) x = (unsigned) x + 1;

これは、GCC によって次のように解釈されます。

x = (uint8_t) (unsigned) ((unsigned) x + 1);

これが結果として入る理由であり、0それが に割り当てられます。x0y

この拡張機能は、GCC のドキュメントでは非推奨と呼ばれています。

于 2012-10-11T14:26:10.670 に答える
1

これを開始するには、有効なCコードではありません。どのようにコンパイルしたかわかりませんが、リンクには出力が表示されるので、この1つの主要な仮定に基づいて何が起こっているのかを説明します。


この行unsigned y = ++((unsigned x));では、2番目の行unsignedがコンパイラーによって削除されていると思います。したがって、ビルドできるのはなぜですか。


だから、それを仮定すると...

uint8_t x = 0xff;    // 8 bit value, max is 255(10) or 0xFF(16)
unsigned y = ++((unsigned)x); 

xこれで、そのタイプの最大値がすでに設定されています。++を介して+1すると、yの値が得られない理由を知りたいと思います0x100

xは8ビットであり、型キャストしても8ビットであるという事実は変わりません。だから私たちが言うとき:

++x

インクリメントしていますxx=x+1)。したがって、符号なしの8ビット値が最大であり、それに1を追加すると、0にラップアラウンドされます。したがって、0yになります。

これを機能させたい場合は、次のようにすることができます。

int main(void) 
{
    unsigned char x = 0xFF; //I'm using char because it's 8 bit too
    unsigned int y = 1+x;   //no need to typecast, we're already unsigned
    printf("%#x %#x\n", x, y);
    return 0; 
} 

x==0xFFこれで、期待値(およびy==0x100)を取得できます。

于 2012-10-11T14:34:20.250 に答える
0

これを試して:

uint8_t x = 0xff;
unsigned y = ((unsigned)x) + 1;

(unsigned) x2バイトの値になっているため、期待どおりに出力されます0x0100

今これを試してみてください:

uint8_t x = 0xff;
++x;

の値はに0xff ラップアラウンド0x00ます。

于 2012-10-11T14:34:42.107 に答える
0

私はあなたの抜粋にいくつかの小さな透明性コードを入れました.それはすべてを説明しています.

#include <stdio.h>
#include <stdint.h> // not needed

int main(void) {
  uint8_t x = 0xff;
  printf("%d\n", sizeof(x));
  unsigned y = ++((unsigned)x); 
  printf("%d\n", sizeof(y));
  printf("0x%x\n", y);
  printf("%d\n", sizeof(y));
  return 0;
}

そして出力は

1      // size of x
4      // size of y before computation
0x100  // computed value of y from your code
4      // size of y after computation

最初に注意すべきことは、sizeof(y)が計算全体で一定に保たれることです。
アウトプットから、

  • uint8_t= 1 バイト
  • unsigned= 4 バイト

reallocC でキャストを行うときは、 「ブロックから持っているこのデータを取得し、メモリ内のサイズをキャストしたいサイズに増やして (または減らして)、次に返す」という暗黙の呼び出しと考えてください。新しいブロックの同じデータ。

そして、私たちのサイズunsignedから、1 バイト操作からの計算結果に適合する十分なスペースがあります。

コードをバイトレベルの詳細で再説明すると、

x               = 11111111                         = 0xff  (in a byte)
(unsigned)x     = 00000000000000000000000011111111 = 0xff  (in a word)
++((unsigned)x) = 00000000000000000000000100000000 = 0x100
于 2012-10-11T14:54:32.800 に答える