There's this code I'm compling, which has the line:
snprintf(target, 11, "%02ld-%02ld-19%02ld", day, month, year);
... which is executed after it has been verified that all 3 values are valid; and specifically, that year is between 0 and 99.
However, recent versions of GCC, when run with -Wextra
, complain:
warning: ‘%02ld’ directive output may be truncated writing between 2 and 20 bytes
into a region of size 3 [-Wformat-truncation=]
I would rather not entirely disable this warning; nor even disable it locally. Instead, I am wondering if I could somehow "convince" GCC of the value range for the three arguments, preventing the warning.
Yes, this is rather ugly code that reinvents the wheel, and locale-specific routines for date formatting should be used, no need to lecture me; not my code.
if I could somehow "convince" GCC of the value range for the three arguments, preventing the warning.
Let the compiler know that all values used are of 1-2 digits with reduced range type, &
, %
, /
or etc.
In this case, recommend unsigned math and %
.
(Note: recall some_int%100
results are in the range -99 to 99, up to 3 characters, hence the reason for unsigned math.)
char target[11];
// dd -dd -19dd \0 0-99 0-99 0-99
snprintf(target, sizeof target, "%02lu-%02lu-19%02lu", day%100lu, month%100lu, year%100lu);
A smart enough compiler will see %
and analyse accordingly.
Since month and day are in the range 1-12 and 1-31, could use month & 15, day & 31
, but that micro optimization lacks clarity.
If day%100lu
brings up an undesirable warning about mixed sign-ness, then
snprintf(target, sizeof target, "%02u-%02u-19%02u",
(unsigned)day%100u, (unsigned)month%100u, (unsigned)year%100u);
or simply use a wider target
;-)
Perhaps the below if a generous buffer is not prohibitive.
#define CHAR_PER_LONG_N (CHAR_BIT*sizeof(long)/3+3)
#define DATE_FMT %02ld-%02ld-19%02ld"
#define BUF_N (sizeof DATE_FMT + 3*CHAR_PER_LONG_N)
char target[BUF_N];
snprintf(target, sizeof target, DATE_FMT, day, month, year);