オプションのフォーマットされたメッセージを使用して、標準に準拠したアサートマクロを実装するにはどうすればよいですか?

ダンラ

オプションのフォーマットされたメッセージを使用して、標準に準拠したアサートマクロを実装する方法は何ですか?

私が持っているものはclangで機能しますが、オプションのメッセージなしでマクロが使用されたとき-Wgnu-zero-variadic-macro-argumentsに(たとえば、経由で-Wpedanticオンにすると、(正しく)警告がトリガーされます。ワンドボックス

#define MyAssert(expression, ...)                                      \
    do {                                                               \
        if(!(expression))                                              \
        {                                                              \
            printf("Assertion error: " #expression " | " __VA_ARGS__); \
            abort();                                                   \
        }                                                              \
    } while(0)
ヤルチュ

私は特に誇りに思っていない解決策を持っています。

最初の引数は、次を使用してプレーン形式および文字列として取得できます。

#define VA_ARGS_HEAD(N, ...) N
#define VA_ARGS_HEAD_STR(N, ...) #N

使用法では、警告受け取らないようにするためにVA_ARGS_HEAD(__VA_ARGS__, )、(余分な,)を実行しVA_ARGS_HEADて、単一のパラメーター(StoryTellerの回答から取得したトリックで使用されないようにする必要があることに注意してください

次のヘルパー関数を定義します。

#include <stdarg.h>
#include <stdio.h>

inline int assertionMessage(bool, const char *fmt, ...)
{
    int r;
    va_list ap;
    va_start(ap, fmt);
    r = vprintf(fmt, ap);
    va_end(ap);
    return r;
}

アサーションにフォーマット文字列がある場合、関数はそのままで機能しますが__VA_ARGS__boolが唯一の引数である場合、フォーマット文字列がありません。そのため__VA_ARGS__、呼び出し時に別の空の文字列を追加します

#define MyAssert(...)                                                          \
    do {                                                                       \
        if(!(VA_ARGS_HEAD(__VA_ARGS__, )))                                     \
        {                                                                      \
            printf("Assertion error: %s | ", VA_ARGS_HEAD_STR(__VA_ARGS__, )); \
            assertionMessage(__VA_ARGS__, "");                                 \
            abort();                                                           \
        }                                                                      \
    } while(0)

名前にassertionMessageが含まprintfいないこと注意しくださいこれは意図的なものであり、コンパイラーが追加の""引数を使用して呼び出しに対してフォーマット文字列関連の警告を出すことを回避することを目的としています。これの欠点は、フォーマット文字列に関連する警告が役立つときに表示されないことです。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ