質問

GCCの-Wconversion警告フラグを使用してプロジェクトを構築しています。 (gcc(Debian 4.3.2-1.1)4.3.2)64ビットGNU / Linux OS /ハードウェア。どこでタイプを混合したか、どのタイプを使用すべきかについて明確さを失ったかを識別するのに役立ちます。

警告をアクティブにする他のほとんどの状況ではあまり役に立たないので、これらをどのように処理するのかを尋ねています:

enum { A = 45, B, C };   /* fine */

char a = A;              /* huh? seems to not warn about A being int. */
char b = a + 1;          /* warning converting from int to char */
char c = B - 2;          /* huh? ignores this *blatant* int too.*/
char d = (a > b ? b : c) /* warning converting from int to char */

上記のテストの予期しない結果( a c のケース)のため、これらの違いについても説明を求めています。

編集:そして、これらをすべて(char)でキャストして警告を防ぐのは過剰なエンジニアリングですか?

Edit2:いくつかの追加のケース(上記のケースに続く):

a += A;         /* warning converting from int to char */
a++;            /* ok */
a += (char)1;   /* warning converting from int to char */

それ以外に、私が求めているのは主観的であり、一部の開発者が all 警告の削除を提唱していると考える場合、このような場合に他の人がどのように変換警告に対処するかを聞きたいです。

やえ:

可能な解決策の1つは、 char sではなく int sを使用することです。実際、より多くのメモリが必要なだけでなく、次のコードで示すように、速度も遅くなります。数学式は、 -Wconversion でビルドされたときに警告を取得するためだけにあります。変換のため、 char 変数を使用するバージョンは int sを使用するバージョンよりも実行が遅いと想定しましたが、私の(64ビットデュアルコアII)システムでは int バージョンは遅いです。

#include <stdio.h>

#ifdef USE_INT
typedef int var;
#else
typedef char var;
#endif

int main()
{
    var start = 10;
    var end = 100;
    var n = 5;
    int b = 100000000;
    while (b > 0) {
        n = (start - 5) + (n - (n % 3 ? 1 : 3));
        if (n >= end) {
            n -= (end + 7);
            n += start + 2;
        }
        b--;
    }
    return 0;
}

-DUSE_INT をgccに渡して、上記のスニペットのintバージョンをビルドします。

役に立ちましたか?

解決

/ * int * / と言うとき、それについての警告を与えているということですか? -Wconversion を使用したgcc 4.0.1または4.2.1のこのコードでは、警告はまったく表示されません。コンパイラはこれらの列挙型を定数に変換しています。コンパイル時にすべてがわかっているため、警告を生成する理由はありません。コンパイラーはすべての不確実性を最適化できます(以下は4.2.1のIntelです):

    movb    $45, -1(%rbp)    # a = 45
    movzbl  -1(%rbp), %eax
    incl    %eax
    movb    %al, -2(%rbp)    # b = 45 + 1
    movb    $44, -3(%rbp)    # c = 44 (the math is done at compile time)
    movzbl  -1(%rbp), %eax   
    cmpb    -2(%rbp), %al
    jle     L2               
    movzbl  -2(%rbp), %eax
    movb    %al, -17(%rbp)
    jmp     L4
L2: 
    movzbl  -3(%rbp), %eax
    movb    %al, -17(%rbp)
L4:
    movzbl  -17(%rbp), %eax
    movb    %al, -4(%rbp)    # d = (a > b ? b : c)

これは、最適化をオンにしないで行われます。最適化により、コンパイル時にbとdが計算され、最終値がハードコードされます(実際に必要な場合)。ポイントは、gccがすでに解決済みであり、すべての可能な値が char に収まるため、ここで問題が発生しないことです。

編集:これを多少修正させてください。 b の割り当てでエラーが発生する可能性があり、コンパイラーは確実であってもそれをキャッチしません。たとえば、 b = a + 250; の場合、 b がオーバーフローすることは確実ですが、gccは警告を発行しません。これは、 a への割り当てが正当であり、 a char であり、数学が正しくないことを確認するのはコンパイラの問題ではないためです。実行時にオーバーフローしません。

他のヒント

おそらく、コンパイラーはすべての値がcharに収まることを既に確認できているので、警告を表示しません。コンパイルの開始時に enum が解決されることを期待しています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top