1

次のプログラムでは

#include<stdio.h>   
int main()    
{    
    char i=0;    
    for(i<=5 && i>=-1;++i;i>0)   
        printf("%d\t",i);
    return 0;    
}    

「i」は 1 から 127 まで、次に -128 から -1 まで出力されます。

これはなぜですか?

4

7 に答える 7

14

これは、私がこれまでに見た中で最も不正な for ループであるに違いありません。for ループは次のようにフォーマットされます。

for ( initalization; condition; update )

forループの開始時にinitialization発生します。これは通常、 のようなものi = 0です。各ループの先頭で、condition(通常はのようなものi < 5) が評価され、ループを続行する必要があるかどうかを確認し、ループを続行する必要がある場合は、updateが実行され (通常はのようなもの++i)、ループがもう一度実行されます。

ここで起こっていることは、ループが条件として使用されているため、 が値に評価された++iときにのみ終了するため、 から開始して から のオーバーフローまでインクリメントし、 に達するまでインクリメントを続け、その時点で と に評価されます。ループは終了します++i01char i128-127-1++i0

編集

したがって、あなたのコードによればi<=5 && i>=-1、ループの最初の繰り返しの最初に実行され(これはまったく何も達成されません)、++iブール値の状態が評価されます(これは0開始され、事前インクリメントを使用すると、評価は1したがって、0ブール値が通過するわけではありません)、次にexecutesのupdateセクションがi>0実行されますが、これも何もしません。

EDIT2

あなたの質問が本当になぜそれが起こるのかについてであるなら1,2....128,-127,-126....-1、ヨアヒムはその行動について非常に良い説明を提供しました

于 2013-02-28T14:28:25.580 に答える
3

朗報: あなたの実装でcharは、署名されています!

また、i127 は signed に収まる最大の正の値であるため、 の値が 127 から -128 にオーバーフローしcharます。

編集:実際には、実装の署名についてはわかりませんcharが、ループは完全に壊れています:

それはおそらく

for (i = 0; i <= 5; i++)

しかし、それは単なる推測です。解釈するのは難しいです。

于 2013-02-28T14:25:42.610 に答える
2

Acharは、コンパイラの符号付き 8 ビット整数です。-128 から +127 までの値を表すことができます。ループ終了条件は++iであり、C ではゼロ以外の値はすべて true と見なされるため、++iis が 0 になるまでループしiます-1

if が 127 から -128 になる理由は、符号付き整数がコンピューターでどのように機能するかによるものです。127 のバイナリ ビットは01111111で、-128 のビット パターンは です1000000。に 1 を追加する01111111と、 になり10000000ます。

全体として、forループは意味がありません。構文的には正しいですが、意味がありません。for ループがどのように機能するかの説明については、Dan F による回答を参照してください。

于 2013-02-28T14:27:08.227 に答える
2

2 の補数表現について読みたいと思うかもしれません

于 2013-02-28T14:28:23.723 に答える
1

プログラムは、出力時に "i" を 8 ビットの符号付き整数として解釈します。つまり、符号に 1 ビット、データに 7 ビットを意味します。これにより、有効な値の範囲は -128 から 127 になります。

「for」ループは、printf の前に i をプリインクリメントするため、最初のパスの値は 1 になり、インクリメントは i+1=128 まで続きます。これにより、符号付き整数の符号ビットが反転し、++ までループが実行されます。 i は i を 0 にします。

于 2013-02-28T14:28:47.623 に答える
1

余談ですが、その for ループはひどいものです。あなたはそれがはずであることを知っていますよfor(intialisation; end condition; increment)ね?

ともかく。i は 0 に初期化されます。forループの最初のラウンドは、事前インクリメントを持つ終了条件(++i)をテストしています。したがって、i は 1 にインクリメントされ、ループが実行されて 1 が出力されます。

今繰り返します。各ループは、終了条件テストが i を事前にインクリメントしているため、i に対して 1 つ高い値を出力します。

最終的には 127 に達します。その後、128 に増加しますが、符号付き整数を期待する "%d" として出力しているため、2 の補数を使用すると、これは -128 と解釈されます。

その後、インクリメントは 255 まで続きます (-1 として出力されます)。次のプレインクリメントでオーバーフローが発生するため、i は再び 0 になり、その時点で「終了条件テスト」が false と評価され、ループが停止します。

于 2013-02-28T14:30:35.547 に答える
1

このプログラムでは、for ループが非常に奇妙に使用されています。「i<=5 && i>=-1」をチェックしてループ変数を初期化します。代入は行われません。ループ中に、i = -1 になるまで真である条件「++i」を評価します。増分ステップでは、数値がゼロより大きいかどうかを確認するだけです。

あなたは実際に次のことを行います:

for(i = 1; i != 0; i++)
{
    printf("%d\t",i);
}

127 を超えるオーバーフローでは、1 から 127 および -128 から -1 の数値が得られます。

于 2013-02-28T14:31:34.727 に答える