-Wformat-truncation-我可以避免它而不是禁用警告吗?

时间:2019-12-09 17:27:15

标签: c printf gcc-warning format-truncation

我正在编译此代码,其中包含以下行:

snprintf(target, 11, "%02ld-%02ld-19%02ld", day, month, year);

...,这在验证所有3个值均有效之后执行;具体来说,该年份介于0到99之间。

但是,最新版本的GCC与-Wextra一起运行时会抱怨:

warning: ‘%02ld’ directive output may be truncated writing between 2 and 20 bytes
into a region of size 3 [-Wformat-truncation=]

我宁愿不完全禁用此警告;甚至在本地禁用它。相反,我想知道是否可以以某种方式“说服”三个参数的值范围的GCC,以防止出现警告。

是的,这是重塑轮子的丑陋代码,应该使用特定于语言环境的日期格式化例程,无需教我。不是我的代码。

1 个答案:

答案 0 :(得分:2)

  

如果我能以某种方式“说服”三个参数的值范围的GCC,以防止出现警告。

让编译器知道使用的所有值都是1-2位数字,其范围类型为&%/等。

在这种情况下,建议使用无符号数学和%
(注意:召回some_int%100的结果范围是-99到99,最多3个字符,因此是未签名数学的原因。)

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);

足够聪明的编译器将看到%并进行相应的分析。


由于月和日的范围在1-12和1-31之间,因此可以使用month & 15, day & 31,但是这种微优化不够清晰。


如果day%100lu提出了关于混合符号性的不良警告,则

snprintf(target, sizeof target, "%02u-%02u-19%02u",
    (unsigned)day%100u, (unsigned)month%100u, (unsigned)year%100u);

只需使用更宽的target;-)

如果慷慨的缓冲区不是禁止的话,也许在下面。

#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);