使用 snprintf 时与目标警告相同的表达式

Same expression as the destination warning when using snprintf

(我看过问题19202368, 40095973 and 1775403

我有这个:

char data[32];
memset(data, '[=10=]', sizeof(data));
snprintf(data, sizeof(data), "%s - %d", aCharArray != NULL ? aCharArray : "", anInt);

在某些 compilers/architectures 上编译时会产生此警告: warning: argument to 'sizeof' in 'int snprintf(char*, size_t, const char*, ...)' call is the same expression as the destination; did you mean to provide an explicit length? [-Wsizeof-pointer-memaccess]

aCharArrayanInt 都可以是函数的局部变量或作为参数传递。这是一个通用示例,也是我使用的通用方法(使用 memset 进行初始化并且更喜欢 snprintf 而不是 sprintf)。我知道如果 data 是本地的,我可以使用与声明它时相同的大小,但我更愿意只在声明中指定一次大小;这样以后改起来也方便

此外,snprintf 将避免溢出并将 [=20=] 放在末尾。 strlen 将对作为参数传递给函数的 char* 有效,但它对新初始化或空的(即 "")毫无意义 char[].

因此,我没有提供字符串长度,因为它可能为 0,但我确实想提供数组的大小。

这种方法是否正确,还是我遗漏了一些注意事项?

附带说明一下,识别切换参数的编译器标志是什么?即,使用上面的:

snprintf(data, sizeof(data), "%s - %d", anInt, aCharArray);

我认为这是在警告您 data(在第一个参数中使用)与 sizeof 中的数据相同,并且 data 可能是一个指针,而不是一个数组(取决于范围)。

如果是数组,您将获得 sizeof(char) * count 个元素,但如果是指针,您将获得 sizeof(char *).

这是错误的常见来源,部分原因是经常看到像 sizeof(buffer) / sizeof(buffer[0]) 这样的表达式来获取数组中元素的最大数量。不管buffer是char buffer[n]还是char *buffer都会编译,但是结果不一样。

如果您满意,请检查您的编译器文档以查看如何抑制特定警告,尽管您也可以重组代码(例如,将数组大小设置为 #define)。

我不明白 identify switched parameters 在你的旁注中,你需要按照格式字符串中的相同顺序放置参数。

警告是由于将相同的表达式传递给 snprintf 作为第一个参数和传递给 sizeof 的参数作为第二个参数。这样使用同一个指针就产生了。

与您发布的内容相反,data 是一个 指针 ,而不是违规代码中的数组。

这个警告是救命稻草,但措辞是灾难性的。如果 data 是一个数组,则不会生成它,但文本似乎仍然适用:

 argument to 'sizeof' in 'int snprintf(char*, size_t, const char*, ...)' call is the same expression as the destination; did you mean to provide an explicit length? [-Wsizeof-pointer-memaccess]

传递显式长度确实不如使用sizeof(array)一致,但sizeof(array)风险更大,因为array是实际数组还是指向指针的指针并不明显调用站点。此警告针对标准功能解决了此问题,但遗憾的是似乎无法为其他功能启用它。

这里是gcc documentation的解释:

-Wsizeof-pointer-memaccess

Warn for suspicious length parameters to certain string and memory built-in functions if the argument uses sizeof. This warning triggers for example for memset(ptr, 0, sizeof(ptr)); if ptr is not an array, but a pointer, and suggests a possible fix, or about memcpy(&foo, ptr, sizeof(&foo));. -Wsizeof-pointer-memaccess also warns about calls to bounded string copy functions like strncat or strncpy that specify as the bound a sizeof expression of the source array. For example, in the following function the call to strncat specifies the size of the source string as the bound. That is almost certainly a mistake and so the call is diagnosed.


void make_file(const char *name)
{
 char path[PATH_MAX];
 strncpy (path, name, sizeof path - 1);
 strncat (path, ".text", sizeof ".text");
 …
}

The -Wsizeof-pointer-memaccess option is enabled by -Wall.

-Wsizeof-array-argument

Warn when the sizeof operator is applied to a parameter that is declared as an array in a function definition. This warning is enabled by default for C and C++ programs.

要允许编译器对 printfscanf 函数族的参数进行类型检查,您应该为 gcc 传递 -Wall -Wextra -Werror,为 clang 传递 -Weverything -Werror