-Wformat-truncation - 我可以避免它而不是禁用警告吗?
-Wformat-truncation - can I avoid it rather than disable the warning?
我正在编译这段代码,其中包含以下行:
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=]
我不想完全禁用此警告;甚至在本地禁用它。相反,我想知道我是否可以以某种方式 "convince" 三个参数的值范围的 GCC,从而防止警告。
是的,这是重新发明轮子的相当丑陋的代码,并且应该使用特定于语言环境的日期格式化例程,不用教我;不是我的代码。
if I could somehow "convince" GCC of the value range for the three arguments, preventing the warning.
让编译器知道所有使用的值都是 1-2 位数字,缩小范围类型,&
、%
、/
等
在这种情况下,建议使用无符号数学和 %
。
(注意:回忆 some_int%100
结果在 -99 到 99 范围内,最多 3 个字符,因此是无符号数学的原因。)
char target[11];
// dd -dd -19dd [=10=] 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);
我正在编译这段代码,其中包含以下行:
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=]
我不想完全禁用此警告;甚至在本地禁用它。相反,我想知道我是否可以以某种方式 "convince" 三个参数的值范围的 GCC,从而防止警告。
是的,这是重新发明轮子的相当丑陋的代码,并且应该使用特定于语言环境的日期格式化例程,不用教我;不是我的代码。
if I could somehow "convince" GCC of the value range for the three arguments, preventing the warning.
让编译器知道所有使用的值都是 1-2 位数字,缩小范围类型,&
、%
、/
等
在这种情况下,建议使用无符号数学和 %
。
(注意:回忆 some_int%100
结果在 -99 到 99 范围内,最多 3 个字符,因此是无符号数学的原因。)
char target[11];
// dd -dd -19dd [=10=] 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);