C printf cross-platform format without warnings [duplicate]

半世苍凉 提交于 2019-12-26 07:18:09

问题


How do you write code to compile cross-platform without warnings. For example, I don't get warnings on x64 platform, but I do on ARM (raspberry PI):

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

Needless to say I don't want to disable warnings.

More examples and scenarios:

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 is probably the highest offender:

Basic use of 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 is equivalent of printf for Mbed OS platform. Yes, I compile on Mbed OS and Linux.


回答1:


For size_t, assuming you have a sufficiently modern C library, use %zu.

If you can't use the z modifier (some older libraries unfortunately don't support it), cast to a wide-enough known type when printing, and then use a width specifier appropriate to that type:

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

This works as long as you're never working with a size larger than 4 billion or so, i.e. that can fit in 32 bits. If you're on a system where size_t is 64 bits but long is 32, you've theoretically got the problem of a size which size_t can hold but %lu can't print. Whether this is a problem for you, and what to do if it is, is up to you. (The ideal solution, if your library supports it, is to go back to %zu, which is the preferred solution and doesn't have this problem in 32-bit, 64-bit, or any other sized environments. Or I guess you could use unsigned long long and %llu.)




回答2:


This particular warning can be avoided by using explicitly sized integers instead of the native data types.

#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

The trick with the sized integers is that if, for example, long were 32-bits on one platform, but 64 bits on another, any uses of long would be non-portable. But int64_t will always be 64-bits, or else it simply won't exist on the given platform.

In your case specifically, your code seems to be presuming that size_t will always be 64-bits, but there's no guarantee of that. So you should be using uint64_t instead, which guarantees that whatever underlying data type it ends up using, it will be 64 bits (and unsigned, which is the only guarantee associated with size_t).



来源:https://stackoverflow.com/questions/46569942/c-printf-cross-platform-format-without-warnings

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!