假设我有一个函数,它接受一个int *p,我知道一个事实只指向0到99之间的值。但是,编译器并不知道这一点,所以如果我这样写:
char buffer[3];
snprintf(buffer, "%02d", *p);我得到了一个警告(至少在GCC 8.x上)-它类似于:
warning: ‘%02d’ directive output may be truncated writing between 2 and 11 bytes into a region of size 2 [-Wformat-truncation=]
snprintf(buffer, "%02d", *p);我应该如何规避这个警告?
发布于 2019-03-22 17:55:28
我可以想出三种方法来避免警告:
使用GCC编译指示的
#if __GNUC__ >= 8#杂注__GNUC__诊断推送#杂注GCC诊断忽略“-W格式截断”#endif snprintf( >=,"%02d",*p);#if __GNUC__>=8#杂注GCC诊断弹出#endif
Buffer3 clamped_value =and print that instead of(*p,0),99)max*p`。snprintf(缓冲区,"%02d",clamped_value);
字符buffer3+9;snprintf(缓冲区,"%02d",p);
但这些我都不太喜欢。第一种方法不太安全(而且更冗长);第二种方法浪费时钟周期,第三种方法浪费堆栈空间。
发布于 2020-01-31 01:58:52
这段代码在我的GCC 8.3.1上编译和运行得很好:
#include <stdio.h>
#define BUF_SZ 3
int main(void)
{
int foo = 99;
int *p = (int *)&foo;
char buffer[BUF_SZ];
snprintf(buffer, BUF_SZ, "%02d", *p);
fprintf(stdout, "%s\n", buffer);
return 0;
}me@localhost:/tmp$ gcc -v 2>&1 | grep "gcc version"
gcc version 8.3.1 20190223 (Red Hat 8.3.1-2) (GCC)
me@localhost:/tmp$ gcc -Wall test.c && ./a.out
99也许这个版本的GCC没有这个问题,但我在上面确实注意到你有snprintf(buffer, "%02d", *p); -它根本不应该编译,因为你缺少了snprintf的大小参数。
此外,值得注意的是,使用以下差异,GCC 8.3.1确实会像预期的那样抛出错误:
me@localhost:/tmp$ diff test.c test_format-truncation-warning.c
11c11
< snprintf(buffer, BUF_SZ, "%02d", *p);
---
> snprintf(buffer, BUF_SZ, "%03d", *p);对于那些偶然发现本页面寻找更通用的-Wformat-truncation警告的“变通办法”的人。这里使用了memcpy(),尽管我怀疑-Wformat-truncation的作者是否打算将其用作strncpy()的替代方法。
#if USE_STRNCPY
/* Note that using size of 'NAME_MAX' is just to prevent recent versions
* of GCC from throwing '-Wformat-truncation' errors. Otherwise, a char
* buffer of len UUID_STR_LEN would be fine.
*/
char tmp_fname[NAME_MAX + 1] = {0};
strncpy(tmp_fname, input_file_name, NAME_MAX);
#else
char tmp_fname[UUID_STR_LEN] = {0};
memcpy((void *)tmp_fname, (void *)input_file_name,
MIN(UUID_STR_LEN - 1, strnlen(input_file_name, UUID_STR_LEN - 1));
#endifhttps://stackoverflow.com/questions/55297018
复制相似问题