6

私は C でのプログラミングにあまり詳しくありません (この言語でいくつかの小さなプロジェクトしか行ったことがありません) が、私の教授は今日の C の動作について何か言っていて、少し混乱しました。

彼が言ったことは、このコードはまったく何も出力しない場合があるということでした (私はボード上にあったものを正確にコピーしました。「印刷」は C にはないので、これは C の疑似コードだと思います):

    int a = ___________;
    int b = ___________;

    if (a < b)
   print (“&lt;“);
    if (a > b)
   print (“&gt;”);
    if (a==b)
   print(“=”);

基本的に、これらの条件のいずれも満たされない int 変数に格納できるものがあります ( _ __ _は明らかに実際のコードではなく、何かがあることを表しているだけです)。それらの空白を埋める int 数値である必要は必ずしもありません...それは世界中の何でもかまいません (そして、このコードの前に起こったことがあるかもしれません)。

それらの空白を埋めることができ、結果をもたらさないのは何ですか? また、その理由は何ですか?

ps - オーバーフロー、未定義の動作、範囲外エラーなどと関係がありました

pps - この教授が間違っていたとはとても信じられません。彼は、私がこれまで接触した誰よりもプログラミングに精通しています。これが真実である場合があると私は確信しています。

4

8 に答える 8

4

必要なのは、int初期化の1つが実行時例外を生成することだけです。その後、プログラムは比較テストの前に終了します。例えば

int b = *(int *)0;
于 2011-05-13T10:27:52.313 に答える
2

重要なのは_の部分だと思います。下線部にコード結果の未定義の動作が含まれており、比較を含む次のコードが未定義の動作に関して「賢い」コンパイラによって最適化される場合、このコードの最終的な動作は未定義です。そして、何も印刷しないことは、合理的な未定義の動作です。

ps ウィキペディアによると、ゼロによる除算は未定義の動作になりますが、ほとんどのコンパイラはそれをエラーと定義しています。また、IIRC 符号付き整数のオーバーフローも未定義の動作を引き起こしますが、これも通常、実行時例外やコンパイル エラーの原因となります。したがって、 a と b が次のように宣言されている場合

int a = 1 / 0;
int b = INT_MAX + 1;

あなたの教授が説明する状況が発生する可能性があります。ただし、動作は定義されていないため、コンパイラがプログラムの動作を選択するものは何でも、標準に準拠していると見なされる可能性があることに注意してください。

于 2011-05-13T10:17:18.330 に答える
1

1 の補数で int 数値を使用するアーキテクチャの場合、2 つのゼロが存在します。1 つはすべてのビットが 0 に設定され、もう 1 つはすべてのビットが 1 に設定されたもので、別名正と負のゼロです。両方のゼロは等しいはずですが、バグのあるコンパイラはそれを認識しない場合があります;-)

于 2011-05-13T10:28:40.417 に答える
0

「このコードの前に起こったことがあるかもしれない」とすると...

#include <stdio.h>
#include <math.h>

int main(void)
{

#define int float

    int a = nanf(NULL);
    int b = nanf(NULL);

    if (a < b)
       printf("<\n");
    if (a > b)
       printf(">\n");
    if (a == b)
       printf("==\n");

    return 0;
}
于 2011-05-13T10:45:02.853 に答える
0

ps-オーバーフローと関係があるのでしょうか?

私はこれがあなたの教授が意味したことだと思います:

#include <stdio.h>
#include <stdint.h>

int main(int argc, char** argv)
{
    uint8_t a = 100;
    uint8_t b = 200;

    a = a + b; /* a = 300 in your head. This overflows, so 300-256=44 */

    if ( a > b )
    {
        printf("%u > %u", a, b);
    }
    else if ( a < b )
    {
        printf("%u < %u", a, b);
    }
    else
    {
        printf("%u == %u", a, b);
    }

    return 0;
}

具体的には、固定幅の8ビット符号なし整数を使用しています。これは最大8ビット(驚き)を保持でき、256を可能な最大の整数として表します。このサイズで表現できない量をフィールドに追加することで、このフィールドをオーバーフローさせることができます。この場合、残っているのはラップアラウンド効果です。

if比較ロジックは実際にはプロセッサの一部であるため(比較/ジャンプ命令の組み合わせの1つに変換される場合)、実際のあいまいさはありません。問題は、コンピュータ上の数値表現がすべて固定表現であることに気づかずに、それが機能することを合理的に期待してプログラムした可能性があることです。「より少ない、より多い、または等しい」すべてを逃れる可能性のあるレジスターに入れることができるものは何も見えません。

わかりやすくするためにC99で導入された固定サイズの整数を使用し、数値のサイズを小さくして、頭の中でそれを実行できるようにしたことに注意してください。

于 2011-05-13T10:25:20.987 に答える
0

おそらくの定義printは次のとおりです。

void
print(const char*) {    
}
于 2011-05-13T11:02:00.967 に答える
0
a = 0, b = 5 / a : divide by zero
于 2011-05-13T10:39:59.617 に答える
0

int の場合、「特別な」値がないため、これは当てはまりません。

于 2011-05-13T10:22:40.000 に答える