0

次の関数を使用して、ユーザーに自動通知を行います。

#define LOG(...) logger((sizeof((int32_t[]){0, ## __VA_ARGS__})/sizeof(int32_t)-1), __VA_ARGS__)
..................
void informer(int32_t count, ...)
{
    GtkTreeModel *model = 0;
    GtkTreeIter iter;
    model = gtk_tree_view_get_model(GUI.log_view);
    gtk_list_store_append(GTK_LIST_STORE(model), &iter);
    char log_body[16384] = {0};
    /* Add current time */
    GDateTime *now;     
    char *time;
    now = g_date_time_new_now_local ();
    time = g_date_time_format (now, "%c");
    g_date_time_unref (now);
    gtk_list_store_set(GTK_LIST_STORE(model), &iter, LOG_TIME, time,  -1);
    free(time);
    /* Parse input data*/
    va_list ap;
    va_start(ap, count);
    while (count--) {
        if(!count)
        {
            enum error_type type = va_arg(ap, int);
            if(type == OK)
            {
                gtk_list_store_set(GTK_LIST_STORE(model), &iter, LOG_TYPE, "OK",  -1);

            }
.............................................                       
            else
            {
                gtk_list_store_set(GTK_LIST_STORE(model), &iter, LOG_TYPE, "Неизв.",  -1);
            }
            break;
        }
        char* arg = va_arg(ap, char*);
        strcat(log_body," ");
        strcat(log_body,arg);
    }
    va_end(ap);
    gtk_list_store_set(GTK_LIST_STORE(model), &iter, LOG_BODY, log_body,  -1);
}

だからそのような電話で

LOG("Unknown error", "Error!", ERROR);

ここで、ERROR は列挙型で、gcc はコンパイル中に警告を表示します。

警告: ('(anonymous)[1]' の初期化に近い)
警告: 初期化により、キャストなしでポインターから整数が作成されます [デフォルトで有効]
警告: ('(anonymous)[2]' の初期化に近い)
警告: 初期化により整数になりますキャストなしのポインターから [デフォルトで有効]
警告: ('(anonymous)[3]' の初期化の近く)
警告: 初期化により、キャストなしでポインターから整数が作成されます [デフォルトで有効]

コードは完全に機能しますが、これは実際には安全ですか? もしそうなら、それを取り除く方法は?#pragma GCC diagnostic error "-Wpointer-to-int-cast"対応するプッシュとポップで使ってみまし たが効果なし。

4

3 に答える 3

1

LOG マクロの引数の数を数えようとしています。ここで考えられる解決策を見てください。

于 2013-09-16T08:53:13.693 に答える
1

マクロは、すべてのポインター型が同じサイズで、そのサイズが 32 ビットである場合にのみ有効です。最初の条件はほとんどのシステムに当てはまり、プラットフォームが難解なものである可能性が低い場合は無視できますが、2 番目の条件は確かにそうではありません

とはいえ、たとえ安全であっても、警告を発行するコードを残すことはお勧めできません。また、警告をグローバルに抑制することも同様に魅力的ではありません。警告を抑制するには、マクロ定義自体だけでなく、マクロへのすべての呼び出しに抑制を適用する必要があります。この場合、おそらく引数の数を指定する方が簡単です。

于 2013-09-16T08:44:21.953 に答える
1

コードは有効です:

  • ポインター型を使用したの最初の初期化では、uint32_tその値がオーバーフローすることはありません。情報が失われますが、それ以上のものはありません。
  • 次に、そのsizeofような獣のみを使用するため、複合リテラルは評価されません。

とにかく、エラーの観点からは、0パラメーターに対しては機能しないため、gccish, ##トリックと+-1.

他の人が言ったように、コードのユーザーに一連の警告を課すのは本当に悪いスタイルです。そんなものは審査に通らないはずです。

最後に、標準 C (C99) のみを使用して同じ目的を達成するマクロがあります (例: P99P99_NARGから) 。

于 2013-09-16T11:24:03.130 に答える