使用 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]
aCharArray
和 anInt
都可以是函数的局部变量或作为参数传递。这是一个通用示例,也是我使用的通用方法(使用 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.
要允许编译器对 printf
和 scanf
函数族的参数进行类型检查,您应该为 gcc 传递 -Wall -Wextra -Werror
,为 clang 传递 -Weverything -Werror
。
(我看过问题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]
aCharArray
和 anInt
都可以是函数的局部变量或作为参数传递。这是一个通用示例,也是我使用的通用方法(使用 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 formemset(ptr, 0, sizeof(ptr));
ifptr
is not an array, but a pointer, and suggests a possible fix, or aboutmemcpy(&foo, ptr, sizeof(&foo));
.-Wsizeof-pointer-memaccess
also warns about calls to bounded string copy functions likestrncat
orstrncpy
that specify as the bound asizeof
expression of the source array. For example, in the following function the call tostrncat
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.
要允许编译器对 printf
和 scanf
函数族的参数进行类型检查,您应该为 gcc 传递 -Wall -Wextra -Werror
,为 clang 传递 -Weverything -Werror
。