3

gcc 4.7.2 c89

こんにちは、

私はいくつかのメンテナンスに取り組んでおり、次の関数のようなマクロがあります。

#define GET_ERROR() ((errno == 0) ? "None" : strerror(errno))

#define LOG_ERR(fmt, ...)                                               \
    fprintf(stderr, "[ERROR] %s:%d: error [%s] " fmt "\n", __func__, __LINE__, GET_ERROR(), ##__VA_ARGS__)

#define LOG_ASSERT(ARG, fmt, ...) do {                          \
        if(!(ARG)) {                                            \
            char arg_fmt[512];                                  \
            snprintf(arg_fmt, sizeof arg_fmt, "%s, ", #ARG);    \
            strcat(arg_fmt, fmt);                               \
            LOG_ERR(arg_fmt, ##__VA_ARGS__);                    \
            errno = 0;                                          \
            abort();                                            \
        }                                                       \
    } while(0)

LOG_ASSERTはassert関数をシミュレートします。ただし、strerrorerrnoからの追加情報が含まれます。

私がこのように使用しているもの:

LOG_ASSERT(msg_id != -1, "Failed to connect to the message queue [ %d ]", msg_id);

したがって、次のように表示されます。

"msg_id != -1, Failed to connect to the message queue [ -1 ]"

strcatを使用して、fmtの先頭に「msg_id!=-1」というプレフィックスを付けました。

ただし、修正できないように見えるこれらのコンパイルエラーが発生します。簡単なことだと思ったので、簡単なことを見逃してしまったら、別のアイデアを見つけたいと思いました。

error: expected ‘)’ before ‘arg_fmt’
warning: format ‘%s’ expects a matching ‘char *’ argument [-Wformat]
warning: format ‘%d’ expects a matching ‘int’ argument [-Wformat]
warning: format ‘%s’ expects a matching ‘char *’ argument [-Wformat]

一部の人々がこのマクロに同意しないかもしれないことを私は知っています、しかしこれは私が維持しなければならないものです。

提案をありがとう

4

1 に答える 1

4

私の知る限り、文字配列ではなく、定数文字列リテラルのみを連結できます。ここに問題があります。

fprintf(stderr, "[ERROR] %s:%d: error [%s] " fmt "\n", __func__, ....

fmtは文字配列です。フォーマットをコピーするために別のバッファが必要になるか、単に分割することができますprintf

#define LOG_ERR(fmt, ...)                                               \
    fprintf(stderr, "[ERROR] %s:%d: error [%s] ", __func__, __LINE__, GET_ERROR());\
    fprintf(stderr, fmt, ##__VA_ARGS__)
于 2012-12-24T11:15:46.297 に答える