2

次のコードの出力を理解しようとしています: http://phrack.org/issues/60/10.html

参考までにここに引用します:

#include <stdio.h>

int main(void){
        int l;
        short s;
        char c;

        l = 0xdeadbeef;
        s = l;
        c = l;

        printf("l = 0x%x (%d bits)\n", l, sizeof(l) * 8);
        printf("s = 0x%x (%d bits)\n", s, sizeof(s) * 8);
        printf("c = 0x%x (%d bits)\n", c, sizeof(c) * 8);

        return 0;
}

私のマシンで得られる出力は次のとおりです。

l = 0xdeadbeef (32 bits)
s = 0xffffbeef (16 bits)
c = 0xffffffef (8 bits)

ここに私の理解があります: -

代入 s=l、c=l により、s と c が int に昇格され、それぞれ l の最後の 16 ビット (0xbeef) と最後の 8 ビット (0xef) を持つことになります。

Printf は、上記の各値 (l、s、および c) を符号なし整数として解釈しようとします (%x がフォーマット指定子として渡されるため)。出力から、符号拡張が行われたことがわかります。%x は unsigned int を表しているのに、なぜ s と c の印刷中に符号拡張が行われたのでしょうか? s の出力は 0x0000beef であり、c の出力は 0x000000ef であってはなりませんか?

4

2 に答える 2

2

s と c の印刷中に符号拡張が行われたのはなぜですか?

次のコードを見てみましょう。

unsigned char ucr8bit; /* Range is 0 to 255 on my machine */
signed char cr8bit; /* Range is -128 to 127 on my machine */
int i32bit;
cr8bit = MINUS_100;  /* (char)(-100) or 0x9C */
i32bit = cr8bit;     /* i32 bit is -100 or 0xFFFFFF9C */

ご覧のように、数-100は同じですが、その表現は単にs をより広い文字で前に付けているだけではなく、2 の補数システムと1 の補数システムのタイプ0の MSB または符号ビットを前に追加している可能性があります。signed

あなたの例では、より広いタイプとして印刷しようとしているsためc、符号ビットの複製が得られます。


また、コードには未定義および未指定の動作の多くのソースが含まれているため、コンパイラごとに異なる出力が得られる場合があります。(たとえば、一部の実装や他の実装ではassigned charの代わりに使用する必要があります)charcharunsigned charsigned char

l = 0xdeadbeef; /* Initializing l from an unsigned
                   if sizeof l is 32 bit UB as l is signed */
s = l;  /* Initializing with an undefined value. Moreover
           implicit conversion wider to narrower type */
printf("l = 0x%x (%d bits)\n", l, sizeof(l) * 8);  /* Using %x
               to print signed number and %d to print size_t */
于 2015-01-19T06:11:46.477 に答える
1

32 ビットの符号付き整数を使用しています。つまり、正の数には 31 ビットしか使用できません。0xdeadbeef は 32 ビットを使用します。したがって、32 ビットの符号付き整数に割り当てると、負の数になります。

符号なしの変換指定子 %x で表示すると、負の数のように見えます (符号拡張付き)。

short または char にコピーすると、負の数であるというプロパティが保持されます。

これをさらに表示するには、次のように設定してみてください。

l = 0xef;

出力は次のとおりです。

l = 0xef (32 bits)
s = 0xef (16 bits)
c = 0xffffffef (8 bits)

0xef は、32 ビットまたは 16 ビットの変数に配置されたときに正の 8 ビットを使用します。8 ビット数値を符号付き 8 ビット変数 (char) に配置すると、負の数値が作成されます。

負の数の保持を確認するには、逆を試してください。

c = 0xef;
s = c;
l = c;

出力は次のとおりです。

l = 0xffffffef (32 bits)
s = 0xffffffef (16 bits)
c = 0xffffffef (8 bits)
于 2015-02-27T00:10:19.550 に答える