24

gcc は、次のコードで警告を生成しないようです。警告を生成するにはどうすればよいですか?

typedef enum
{
    REG8_A,
    REG8_B,
    REG8_C
}REG8;

typedef enum
{
    REG16_A,
    REG16_B,
    REG16_C
}REG16;

void function(REG8 reg8)
{

}

int main(void)
{
    function(REG16_A);    // Should warn about wrong enum
}
4

6 に答える 6

9

このような動作の理由は、C++ ではなく C コンパイラを使用しているためです。また、C の列挙型は実際には型ではありません。C の列挙型は単に int 定数を保持し、任意の整数および任意の算術演算と自由に組み合わせることができます。

代わりに C++ では、考えたいとおりの実際の列挙型があり、必要な型チェックは言語標準によって伝えられるように行われます。

問題は次の 2 つの方法で解決できます。

  • C++ コンパイラを使用します。

    このようにして、必要に応じて実際の列挙型を取得できます。

  • コードを純粋な C スタイルに変更します。つまり、列挙型を使用しないようにします。C では列挙型は単なる定数セットであり、コンパイラは定数値の順序付けのみを支援します。そして Cでは、渡された定数の「型」の一貫性を維持する責任があります繰り返しますが、C の場合、enum メンバーは単なる int 定数であり、型付きにすることはできません。


#define REG8_A 0
#define REG8_B 1
#define REG8_C 2

#define REG16_A 0
#define REG16_B 1
#define REG16_C 2
于 2011-01-17T13:11:47.193 に答える
6

警告を生成するために私が見ることができる唯一の方法は、裸の列挙型ではなくポインタを渡す準備ができているかどうかです。

typedef enum
{
    REG8_A,
    REG8_B,
    REG8_C
} REG8;

typedef enum
{
    REG16_A,
    REG16_B,
    REG16_C
} REG16;

void function(REG8 * reg8)
{

}

int main(void)
{
    REG16 r = REG16_A;
    function(&r);
    return 0;
}

正確には洗練された解決策ではありませんが、少なくとも次の場合には警告が表示されgcc -Wallます。

$ gcc -Wall warn_enum.c -o warn_enum
warn_enum.c: In function ‘main’:
warn_enum.c:23: warning: passing argument 1 of ‘function’ from incompatible pointer type
$
于 2011-01-12T13:54:31.013 に答える
2

他の人が指摘したように、C は列挙型と基になる整数型を区別しません。(一部のコンパイラには、拡張子としてenums またはtypedefs の型チェックが含まれる場合があります。YMMV です。)

C で型チェックを行うには、s を使用できますが、組み込みの比較演算子と変数に対するstruct機能を使用できなくなります。switchただし、次のようなことを試すことができます。

typedef struct {
    enum {
        reg8_val_A,
        reg8_val_B,
        reg8_val_C,
    } val;
} reg8;
#define reg8_A (reg8){.val = reg8_val_A}
#define reg8_B (reg8){.val = reg8_val_B}
#define reg8_C (reg8){.val = reg8_val_C}
…
bool
is_A_or_B(reg8 reg) {
    if reg.val == reg8_A.val    // one way to compare
        return true;
    switch (reg.val) {
        case reg8_val_B:        // the other way to compare; note that
            return true;        // “case reg8_B.val:” will *not* work
        case reg8_val_C:
            return false;
        default:
            fprintf(stderr, "bad reg value %d\n", reg.val);
            abort();
    }
}

(一部の C99 機能を使用します。)

于 2011-01-18T16:12:30.493 に答える
1

GCC 4.6では、暗黙的な型変換を防ぐためにとオプションを使用する必要があります。Paul Rによって投稿されたコードでエラーが発生します。ただし、元のコードはとにかく正常にコンパイルされます。どうしてか分かりません。-Wconversion-Werror

于 2011-03-12T11:55:54.337 に答える
0
$ g++ test3.cpp -o test3
test3.cpp: In function ‘int main()’:
test3.cpp:22: error: cannot convert ‘REG16’ to ‘REG8’ for argument ‘1’ to ‘void function(REG8)’
于 2011-01-17T12:46:51.643 に答える