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

ein*_*ica 6 c printf gcc-warning format-truncation

我正在编写这段代码,其中包含以下行:

\n\n
snprintf(target, 11, "%02ld-%02ld-19%02ld", day, month, year);\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

然而,最新版本的 GCC 在使用 运行时-Wextra会抱怨:

\n\n
warning: \xe2\x80\x98%02ld\xe2\x80\x99 directive output may be truncated writing between 2 and 20 bytes\ninto a region of size 3 [-Wformat-truncation=]\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n

是的,这是相当丑陋的重新发明轮子的代码,应该使用特定于区域设置的日期格式化例程,不需要教训我;不是我的代码。

\n

chu*_*ica 4

如果我能以某种方式“说服”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);
Run Code Online (Sandbox Code Playgroud)

足够聪明的编译器会%相应地进行查看和分析。


由于月份和日期在 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);
Run Code Online (Sandbox Code Playgroud)

或者只是使用更广泛的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);
Run Code Online (Sandbox Code Playgroud)

  • 所以,你建议引入一个多余的昂贵指令......我想这会起作用,但这是一种不正当的做法。:-( (3认同)