C 这是不是;从指针生成不带强制转换的整数;安全的定义?

C 这是不是;从指针生成不带强制转换的整数;安全的定义?,c,pointers,gcc,casting,c-preprocessor,C,Pointers,Gcc,Casting,C Preprocessor,我使用以下功能自动通知用户: #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_mo

我使用以下功能自动通知用户:

#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为enum,gcc在编译期间显示警告:

警告:(接近(匿名)[1]'的初始化)
警告:初始化从指针生成整数而不进行强制转换[默认启用]
警告:(接近(匿名)[2]'的初始化)
警告:初始化从指针生成整数而不进行强制转换[默认启用]
警告:(接近(匿名)[3]'的初始化)
警告:初始化从指针生成整数而不使用强制转换[默认情况下启用]

代码工作得很好,但这真的安全吗?
如果是,如何摆脱它?我尝试使用
#pragma GCC diagnostic error“-Wpointer to int cast”
进行相应的推送和弹出操作,但没有效果。

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


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

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


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

您正在尝试对日志宏中的参数数量进行计数。请查看。

您正在尝试计算日志宏中的参数数。请查看。

代码有效:

  • 指针类型的
    uint32\t
    的首次初始化将永远不会成功 溢出该值。将会丢失信息,但什么也没有 更多
  • 然后你也只使用
    sizeof
    这样的野兽,所以这个化合物 文字永远不会被计算
从错误的角度来看,无论如何,你的方法对
0
参数不起作用,因此最好删除gccish
,##
技巧和
+-1
游戏

正如其他人所说,向代码的用户强加一系列警告是非常糟糕的风格。这样的事情永远不应该通过审查

最后,有些宏仅使用标准C(C99)来实现相同的目标,例如
P99\u NARG
from.

代码有效:

  • 指针类型的
    uint32\t
    的首次初始化将永远不会成功 溢出该值。将会丢失信息,但什么也没有 更多
  • 然后你也只使用
    sizeof
    这样的野兽,所以这个化合物 文字永远不会被计算
从错误的角度来看,无论如何,你的方法对
0
参数不起作用,因此最好删除gccish
,##
技巧和
+-1
游戏

正如其他人所说,向代码的用户强加一系列警告是非常糟糕的风格。这样的事情永远不应该通过审查


最后,还有一些宏只使用标准C(C99)来实现相同的目标,例如
P99\u NARG
from.

关于指针大小。如果我使用memsize类型,比如size\u t而不是int32\u t,会怎么样?在相应的系统指针上,它将是32位和64位,指向整数类型转换,反之亦然,如果没有类型转换,则不可能实现。计算参数的解决方案可用于同质类型的参数。@user1969104:它不是“我的解决方案”,宏中使用的logger()函数似乎将参数计数作为参数,宏试图自动确定参数计数。更好的解决方案是使用更好的接口编写日志函数。@pugnator:定义的类型intptr\u t或uintptr\u t(在stdint.h中)可能是更好的选择。关于指针大小。如果我使用memsize类型,比如size\u t而不是int32\u t,会怎么样?在相应的系统指针上,它将是32位和64位,指向整数类型转换,反之亦然,如果没有类型转换,则不可能实现。计算参数的解决方案可用于同质类型的参数。@user1969104:它不是“我的解决方案”,宏中使用的logger()函数似乎将参数计数作为参数,宏试图自动确定参数计数。更好的解决方案是使用更好的接口编写日志函数。@pugnator:定义的类型intptr\u t或uintptr\u t(在stdint.h中)可能是更好的选择。您试图实现什么
sizeof((int32_t[]){0,###(uu VA_uargs_u})
看起来不是很有用。是否要计算varg列表中的元素数?还有其他方法可以达到这个目的。你想达到什么目的
sizeof((int32_t[]){0,###(uu VA_uargs_u})
看起来不是很有用。是否要计算varg列表中的元素数?还有其他方法可以实现这一目标。