首页 文章

C printf跨平台格式,没有警告[重复]

提问于
浏览
-2

这个问题在这里已有答案:

如何在没有警告的情况下编写代码来编译跨平台 . 例如,我没有在x64平台上收到警告,但我在ARM(raspberry PI)上收到警告:

警告:格式'%lu'需要'long unsigned int'类型的参数,但参数5的类型为'size_t

不用说我不想禁用警告 .

更多示例和场景:

warning: format ‘%lu’ expects argument of type ‘long unsigned int’, 
but argument 5 has type ‘uint64_t {aka long long unsigned int}’  

uint64_t Created;       // 8 bytes
time_t now = time(NULL);
"Current time: %li sec, %lu nanosecs", now, msg.Created

size_t可能是最高的罪犯:

sizeof的基本用法:

warning: format ‘%lu’ expects argument of type ‘long unsigned int’, 
but argument 4 has type ‘unsigned int’
tr_debug("pbJobs size: %lu", sizeof(pbJobs));

tr_debug相当于Mbed OS平台的printf . 是的,我在Mbed OS和Linux上编译 .

2 回答

  • 0

    对于 size_t ,假设您有一个足够现代的C库,请使用 %zu .

    如果你不能使用 z 修饰符(遗憾的是一些较旧的库不支持它),在打印时强制转换为足够广泛的已知类型,然后使用适合该类型的宽度说明符:

    size_t sz = sizeof(whatever);
    ...
    printf("%lu", (unsigned long)sz);
    

    只要你在 size_t 是64位但是 long 是32的系统上这是有效的,你理论上会遇到 size_t 可以容纳但 %lu 无法打印的大小的问题 . 这对您来说是否是一个问题,以及如果它是该怎么做,取决于您 . (理想的解决方案,如果你的库支持它,是回到 %zu ,这是首选的解决方案,在32位,64位或任何其他大小的环境中没有这个问题 . 或者我想你可以使用 unsigned long long%llu . )

  • 2

    通过使用显式大小的整数而不是本机数据类型,可以避免此特定警告 .

    #include <cstdint>
    
    int8_t a = 15; //usually an alias for char
    uint16_t b = 4980; //usually an alias for unsigned short
    uint32_t c = 1234567890; //usually an alias for unsigned int or unsigned long
    int64_t d = 908070605040302010ll; //usually an alias for long long
    

    具有大小整数的技巧是,例如,如果 long 在一个平台上是32位,而在另一个平台上是64位,则 long 的任何使用都是不可移植的 . 但 int64_talways 为64位,否则它根本不会存在于给定平台上 .

    在具体情况下,您的代码似乎假设 size_t 将始终为64位,但不能保证这一点 . 所以你应该使用 uint64_t ,这保证了它最终使用的基础数据类型,它将是64位(和无符号,这是与 size_t 相关的唯一保证) .

相关问题