5

これは未定義の動作ですか?-128結果として出力されます。

#include<stdio.h>
int main()
{
    char i=-128;
    i=-i;
    printf("%d",i);
}

説明してください。

4

6 に答える 6

8

8 ビット符号付き値の -128 の 2 の補数は -128 です。

バイナリ値を見てください。

元の値: 10000000

補足: 01111111

増分: 10000000

于 2012-06-15T21:23:53.170 に答える
4

これは未定義の動作ではありません。タイプがプラットフォームで署名されていると仮定するとchar、それは実装定義の動作です。(C99、6.3.1.3p3)

i = -i;

iinは最初に-iに昇格され、int次に整数変換によって に変換されます。-i128128char

128への変換charは実装定義であると述べている標準の段落は次のとおりです。

(C99, 6.3.1.3p3) それ以外の場合、新しい型は署名されており、値を表現できません。結果が実装定義であるか、実装定義のシグナルが発生します。

EDIT : 実装定義ですが、ほとんどの実装間で共通の実装動作があります。gccドキュメントが行うべきこと(および他のほとんどのコンパイラが行うこと) は次のとおりです。

幅 N の型への変換の場合、値は型の範囲内になるように 2^N を法として減らされます。信号が発生しない

http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html

すべてのコンパイラがこのように動作するわけではないことに注意してください。一部の (DSP) コンパイラは飽和状態になります。この場合 (そしてまだ signed を想定しているchar)、i = -i;の値の後は にiなります127

于 2012-06-15T21:25:07.063 に答える
1

2 の褒め言葉

-128 = 0b10000000

だからあなたは見つけたい: -(-128):

ステップ 1 (否定):

~(-128) = 0b01111111

ステップ 2 (1 を追加):

0b01111111 + 0b1 = 0b10000000 = -128

したがって、8 ビットの数値では、-(-128) = -128!

于 2012-06-15T21:26:45.533 に答える
0

あなたは署名された文字を使用しています。符号付きの正の 1 バイトの最大値は 127 です。-128 を否定して +128 にしようとすると、-128 にオーバーフローしてしまいます。この動作は、OS とコンパイラに依存している可能性があります。

于 2012-06-15T21:23:38.840 に答える
0

未定義の動作ではありません。

-1 による乗算は、ビットを否定してから 1 を加算することと同じです。

~10000000+1 = 01111111+1 = 10000000

まだ-128です。

于 2012-06-15T21:25:07.080 に答える
0

同じ結果が得られます。

アセンブリは次のとおりです (Microsoft Visual Studio):

; File tmp.c
; Line 5
    push    ebp
    mov ebp, esp
    push    ecx
; Line 6
    mov BYTE PTR _i$[ebp], -128         ; ffffff80H
; Line 7
    movsx   eax, BYTE PTR _i$[ebp]
    neg eax
    mov BYTE PTR _i$[ebp], al
; Line 8
    movsx   ecx, BYTE PTR _i$[ebp]
    push    ecx
    push    OFFSET FLAT:$SG775
    call    _printf
    add esp, 8
; Line 9
    xor eax, eax
; Line 10
    mov esp, ebp
    pop ebp
    ret 0
_main   ENDP

バイナリ値に注意してください。

そして、「2 の補数」演算を覚えておいてください。

それは理にかなっていますか?

====== 補遺 ======

これは本当に簡単です。明確にするのに役立つかもしれないわずかに変更された例を次に示します。

#include <stdio.h>

int
main (int argc, char *argv[])
{
  int i=-128, j, k, l;
  char c = i;
  printf("i: %d == 0x%x; c: %d == 0x%x\n", i, i, c,c);

  j=-i;
  k=~i;
  l=0-i;
  i=-i;
  c=-c;
  printf("%d, %d, %d, %d, %d\n",i,j,k,l,c);
  printf("0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",i,j,k,l,c);
  return 0;
}

結果:

i: -128 == 0xffffff80; c: -128 == 0xffffff80
128, 128, 127, 128, -128
0x80, 0x80, 0x7f, 0x80, 0xffffff80
于 2012-06-15T21:25:53.927 に答える