5

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 */

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

やえ:

考えられる解決策の 1 つは、ints の代わりにchars を使用することですよね?実際には、次のコードで示されているように、より多くのメモリが必要になるだけでなく、速度も遅くなります。数式は、 でビルドしたときに警告を表示するためだけに存在します-Wconversionchar変数を使用するバージョンは、変換のために s を使用するバージョンよりも遅く実行されると想定しましたintが、私の (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;
}

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

4

2 に答える 2

2

あなたが言うとき、/* int */それはあなたにそれについての警告を与えているという意味ですか?gcc 4.0.1または4.2.1を使用したこのコードでは、警告はまったく表示されません-Wconversion。コンパイラはこれらの列挙型を定数に変換しています。コンパイル時にすべてがわかっているため、警告を生成する理由はありません。コンパイラーはすべての不確実性を最適化できます(以下は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であり、実行時に数学がオーバーフローしないようにするのは(コンパイラではなく)あなたの問題だからです。

于 2009-10-29T14:14:13.933 に答える
0

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

于 2009-10-29T13:05:00.030 に答える