9

次のコードをコンパイルします。

#include <string.h>
#define FOO (NULL)

int main(int argc, char *argv[])
{
    char *foo;

    if (FOO)
        foo = strdup(FOO);

    return 0;
}

次のコンパイラ警告が発生します。

foo.c: In function ‘main’:
foo.c:9:3: warning: null argument where non-null required (argument 1) [-Wnonnull]
   foo = strdup(FOO);
   ^

ただし、チェックが原因である場合はstrdup呼び出されません。この警告を回避する方法はありますか?FOONULLif (FOO)

ありがとう!

4

3 に答える 3

6

が引数で呼び出されないstrdupようにするために、句での呼び出しを保護したことは正しいです。strdupNULL

しかし、関数呼び出しの警告を発行するコンパイラの部分は、呼び出しが決して起こらないことを知っている部分と同じではありません。

NULL代わりに、生成された引数式が決して にならないことを保証する式で を覆い隠すことができますNULL

例えば

if (FOO) foo = strdup(FOO?FOO:"");

また

if (FOO) foo = strdup(FOO + !FOO);

strdupこれは、値で呼び出すことができない「明確な」(少なくともコンパイラーNULLにとって) であり、if句は、もはやNULL値ではないもので決して呼び出されないようにします。

この時点で、私たちは手を振って、コンパイラーがすべてを最適化すると言います。

#define NON_NULL(x) ((x)?(x):"")

デバッグ ビルドの場合は、次のようになります。

#define NON_NULL(x) ((x)?(x):(abort(),""))

複数回の評価を回避するために、GNU 拡張機能?:(省略可能な中間節がデフォルトで最初の節に設定されている) を使用する場合があります。(x)

#define NON_NULL(x) ((x)?:"")

デバッグ ビルドの場合は、次のようになります。

#define NON_NULL(x) ((x)?:(abort(),"")

これで、技術的にはよりあいまいですが、明らかにより意味のあるものを提示できます。

if (FOO) foo = strdup(NON_NULL(FOO));

NON_NULLそして、それが何らかの正式な表記と承認であるふりをします。

于 2017-06-23T11:11:29.687 に答える
4

fooifが定義されている場合に値を割り当てることが考えられる場合FOOは、次を試すことができます。

//#define FOO "lorem ipsum"

int main()
{
    char *foo;
    #ifdef FOO
        foo = strdup(FOO);
    #endif
}

また、if必要のないときにコード全体が含まれていないという利点もあります。

于 2014-10-22T13:06:19.953 に答える