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 在编译期间显示警告:

警告:('(匿名)[1]'的近初始化)
警告:初始化从没有强制转换的指针生成整数[默认启用]
警告:('(匿名)[2]'的近初始化)
警告:初始化使整数来自没有强制转换的指针 [默认启用]
警告:('(anonymous)[3]' 的初始化附近)
警告:初始化从没有强制转换的指针生成整数 [默认启用]

代码完美运行,但这真的安全吗?如果是,如何摆脱它?我尝试使用 #pragma GCC diagnostic error "-Wpointer-to-int-cast"相应的推送和弹出但没有效果。

4

3 回答 3

1

该宏仅在所有指针类型的大小相同且该大小为 32 位的情况下才有效。第一个条件对于大多数系统都是正确的,如果您的平台不太可能是深奥的,则可以忽略,第二个条件当然不是。

也就是说,即使它是安全的,留下发出警告的代码也不是一个好主意,因为全局禁止它们同样没有吸引力。要抑制警告,您必须将抑制应用于对宏的每次调用,而不仅仅是宏定义本身,在这种情况下,提供参数计数可能会更容易。

于 2013-09-16T08:44:21.953 回答
1

您正在尝试计算 LOG 宏中的参数数量。请在此处查看可能的解决方案

于 2013-09-16T08:53:13.693 回答
1

代码有效:

  • 具有指针类型的 a 的第一次初始化uint32_t永远不会溢出该值。会丢失信息,但仅此而已。
  • 然后你也只使用sizeof这样的野兽,所以复合文字永远不会被评估。

从错误的角度来看,无论如何,您的参数不适用于0参数,因此最好删除 gccish, ##技巧和使用+-1.

正如其他人所说,向代码的用户强加一堆警告真的很糟糕。这样的事情永远不应该通过审查。

最后,有些宏只使用标准 C (C99) 来实现相同的目标,例如P99_NARGP99开始。

于 2013-09-16T11:24:03.130 回答