2

先に言っておきますが、説明しようとしている問題をほんの数行のコードで再現することはできませんでした (信じてください、私は試しました)。そして、以下に説明する問題を修正しました。なぜそれが起こったのかを突き止めようとしています。

C 用の端末コード エディターを作成しています 。別のアーキテクチャ (具体的には Arm) でテストすると、奇妙なエラーが発生しました。上にスクロールしなくなりました (下にスクロールしません)。この関数呼び出しの問題を次のコードに絞り込みましたmain

} else if ((c + 64) == 'V'){
    edit_scroll (&session, session.max_y / 2);
    session.cursor = session.disp;
    session.flags |= EDIT_FLAG_REPRINT;
} else if ((c + 64) == 'Y'){
    //here
    edit_scroll (&session, -1 * (session.max_y / 2)); /*
                                |                 |
        Removing parenthesis causes compilation errors
        in some platforms.
    */
    session.cursor = session.disp;
    session.flags |= EDIT_FLAG_REPRINT;
 }

edit_scroll負の値が渡されると上にスクロールします (図のように)。これらの 2 つの括弧を追加したときにエラーを修正したところ2147483598、関数呼び出し内で式が評価されていることがわかりました。intこのコンパイルでの最大値はであり、このテストを実行したとき2,147,483,647の のサイズであることに注意してください(変数は端末の高さを表します)。session.max_y100

edit_scroll実装は次のとおりです。

int edit_scroll (struct edit * session, int deltay){
    // I printed deltay at this line, when I determined the value
    int i = session->disp;
    char * data = session->buffer.data;

    if (deltay > 0){
        for (; data[i] && deltay; i++){
            if (data[i] == '\n'){
                deltay--;
            }
        }

        if (!deltay){
            session->disp = i;
        }

    }

    if ((deltay < 0) && (session->disp > 0)){
        for (i--; i > 0; i--){
            if (data[i - 1] == '\n'){
                if (!(++deltay)){
                    break;
                }
            }
        }
        session->disp = i;
    }

    return 0;
}

私が言ったように、小さなテスト プログラムではこのエラーを再現できませんでした。Clang と Gcc でこれを試してみましたが、どちらも同じエラーが発生します。なぜこれはこのような奇数に評価されるのですか? これはコンパイルエラーであると言っても過言ではありませんか?

-1 * session.max_y / 2

アセンブリを表示するのに役立ちますか? もっとソースコードを投稿する必要がありますか? .cファイルだけでも行よりも少し多いため、コード全体を投稿することをためらっています1800

4

2 に答える 2

3

乗算と除算は左結合です。したがって、括弧を削除すると、(-1 * session.max_y) / 2代わりに計算されます-1 * (session.max_y / 2)。その max_y フィールドが符号なしの場合、その除算は、あるケースでは符号拡張を行い、別のケースでは行わないため、異なる結果が生成されます。

于 2013-07-31T03:30:25.803 に答える
1

の値に関係なく、max_y符号なしの場合、 で乗算すると-1、は乗算前に に-1変換されunsigned、結果は になりunsignedます。

負の数を含む何かを行う前に、符号なしをキャストすることをお勧めします。除算を行っていない場合でも、非常に大きな符号なしの結果 (負の数であるはず) を符号付きの型に変換すると、整数オーバーフローと未定義の動作が発生する可能性があります。(このようなオーバーフローがコンパイル エラーの原因であると思われます。それ以外の場合は、すべてが適切に定義されており、間違った方法で行われているためです。)

于 2013-07-31T03:31:29.590 に答える