【C/C++】C4018「signed と unsigned の数値を比較しようとしました」の対処法

C/C++のプログラムのコンパイルは通るのに警告が表示されるといったことはありませんか?

「signed と unsigned の数値を比較しようとしました」というのもコンパイルは通るけど警告が出るというものの一つです。

なぜこのような警告が表示されてしまうのか解説していきます。

C4018「signed と unsigned の数値を比較しようとしました」が発生する原因と解決方法

この警告は扱える数値の範囲が異なるsigned変数とunsigned変数の2つを比較した際に発生します。

 
#include
int main() {
        unsigned int uc = -100;
        int c = 0;
        if (uc < c) {
                printf("同じ値でした");
        }
        else {
                printf("あれれ");
        };
}
クリップボードにコピーする
あれれ?

明らかに-100は0より小さいにもかかわらず実行結果がおかしくなっています。

この警告を解消したい場合は変数の型を統一するようにしましょう。

このような挙動になってしまう原因

C/C++には符号なしと符号ありの2種類があることは知っていますか?

符号ありと符号なしでは扱える数値の範囲が異なっており、int型の場合だと以下のようになります。

int型 符号あり(signed) 符号なし(unsighned)
最小値 -2,147,483,648 0
最大値 2,147,483,647 4,294,967,295

範囲はこの様になっており、範囲外の値を代入・使用しようとするとオーバーフロー・アンダーフローが発生します。

オーバーフローとは

    コンピュータの演算において数値型が表現可能な値の上限を超えること、およびそれによって発生したエラー。「桁あふれ」ともいう。対義語はアンダーフロー。

    出典:Wikipedia – オーバーフロー

    以下のサンプルコードを見てください。

     
    int main() {
            int a = -100;
            unsigned int b = a;
            std::cout << a << std::endl;
            std::cout << b << std::endl;
    }
    クリップボードにコピーする
    -100
    4294967196

    一見すると普通のコードに見えるかもしれませんが、変数a(-100)をマイナスの値を扱えない符号なしint型変数bに代入した影響でアンダーフローが発生しています。

    アンダーフローの影響で数値がおかしくなってしまい、その状態で比較すると条件分岐おかしくなってしまうために「signed と unsigned の数値を比較しようとしました」という警告が表示されるのです。

    気づきにくいバグになりやすいので、C4018警告が表示された場合は気付き次第すぐに修正するようにしましょう。

    現場ですぐに使える! C/C++逆引き大全 560の極意

    C/C++の関数の使い方はわかるけど、どういう場面で使うのかいまいちわからない...
    そういう方に相性抜群の逆引きリファレンス。
    まさか、逆引き系を一冊も持っていないというもったいないことはしていませんよね?
    リファレンスブックを持っていない方は要チェック。

    コメント

    タイトルとURLをコピーしました