【问题标题】:-Wformat-truncation - can I avoid it rather than disable the warning? [duplicate]-Wformat-truncation - 我可以避免它而不是禁用警告吗? [复制]
【发布时间】:2019-12-09 17:27:15
【问题描述】:

我正在编译这段代码,其中有一行:

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 三个参数的值范围,从而防止警告。

是的,这是相当丑陋的代码,它重新发明了轮子,应该使用特定于语言环境的日期格式化例程,无需教我;不是我的代码。

【问题讨论】:

标签: c printf gcc-warning format-truncation


【解决方案1】:

如果我能以某种方式“说服”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);

【讨论】:

  • 所以,你建议引入一个多余的昂贵指令......我想这会起作用,但这是一种不正当的做法。 :-(
  • @einpoklum-reinstateMonica 或者只是一个宽缓冲区 - 没有“昂贵”的指令。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 2023-02-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多