5

列挙型と、すべて列挙型を使用するマクロ定義とメソッドがあります。コンパイルできません。次のコードについて考えてみます。

typedef enum fruits_t
{
    APPLE,
    ORANGE,
    BANANA
} fruits_t;

#define KEY_TO_VALUE(x) ((x == APPLE) ? 0 :  \
                         (x == ORANGE) ? 1 :  \
                         (x == BANANA) ? 2 : \
                         "Undefined")

static void foo(char fruit) {
    if (fruit == KEY_TO_VALUE(APPLE)) {
        /* do something */
    }
}

これはコンパイルされますが、次の警告が表示されます。

warning: pointer/integer type mismatch in conditional expression

warning: comparison between pointer and integer

なんで?私はCに非常に慣れていないので、経験豊富なC開発者にとって明白に思えるかもしれないことを説明していただければ幸いです。私のプログラミング知識のほとんどはJavaベースです。

4

2 に答える 2

13

コンパイラは、プログラム内の各式のタイプを把握しようとしています。

のような式x > 0 ? 5 : "no"は、コンパイラに頭を悩ませます。xがゼロより大きい場合、タイプはですintが、そうでない場合、タイプはconst char *です。intポインタからへの自動変換(およびその逆)がないため、これは問題です。したがって、コンパイラはそれについて警告します。

解決策は、の値が何であってもfruit、の値がKEY_TO_VALUE単一のタイプであることを確認することです。たとえば、「Undefined」(const char *リテラル文字列であるためタイプは)の代わりに、-1などの特別な値を使用できます。

APPLEまた、は値0ORANGEの定数、は値1の定数、値2の定数であることに注意してくださいBANANA(これがどのように機能するかenumです)。KEY_TO_VALUEしたがって、定数にはすでに目的の値があるため、は必要ありません。直接比較することができfruitますAPPLE

if (fruit == APPLE) { ... }
于 2012-11-10T01:44:12.990 に答える
4

C言語では、?:演算子は2番目と3番目のオペランドに次の要件を課します

次のいずれかが2番目と3番目のオペランドに当てはまります。

  • 両方のオペランドは算術型です。
  • 両方のオペランドの構造体または共用体タイプは同じです。
  • 両方のオペランドはvoid型です。
  • 両方のオペランドは、互換性のあるタイプの修飾バージョンまたは非修飾バージョンへのポインターです。
  • 一方のオペランドはポインターで、もう一方はヌルポインター定数です。また
  • 一方のオペランドはオブジェクトまたは不完全な型へのポインターであり、もう一方は修飾または非修飾バージョンのvoidへのポインターです。

char *コードでは、の第2オペランドと第3オペランドとして、算術型とポインタ型(文字列リテラルは型に減衰します)を混合しています?:。これは許可されていません。

非公式に言えば、どうやってそのアイデアを思いついたのですか?どんなタイプのようなものx == BANANA ? 2 : "Undefined"でしょうか?intchar *?他に何かありますか?

ポインタ値と定数の混合0が許可されていることに注意してください。つまり、式x == APPLE ? 0 : "Undefined"は実際には問題なくコンパイルされます。ただし、はnullポインター定数0として解釈され、式全体はポインター型( )を持ち、 trueの場合はnullポインターと評価されます。これはおそらくあなたが意図したものではありません。char *x == APPLE

于 2012-11-10T02:47:28.810 に答える