gcc 4.8在构建时给我一个错误
#include <string.h>
#include <stdio.h>
static inline void toto(char str[3])
{
snprintf(str, sizeof(str), "XX");
}
int main(){
char str[3];
toto(str);
return 0;
}
这是gcc错误
错误:'snprintf'调用中'sizeof'的参数与目标的表达式相同;你的意思是提供明确的长度吗?
注意:我使用-Wall -Werror标志将警告转换为错误。
There is something similar here 在评论中,有人回答了这个问题
“对于固定长度的缓冲区,我通常使用strncpy(dest,src,sizeof(dest)); dest [sizeof(dest)-1] ='\ 0';这可以保证NULL终止并且只是更少麻烦比snprintf更不用说很多人使用snprintf(dest,sizeof(dest),src);相反,当他们的程序任意崩溃时会非常惊讶。“
但这是错误的: gcc 4.8说
“错误:'strncpy'调用中'sizeof'的参数与目标表达式相同;你的意思是提供显式长度吗?[-Werror = sizeof-pointer-memaccess]”
in gcc 4.8 documentation, they are talking about this issue: 他们说:
-Wall的行为已更改,现在包含新警告标志-Wsizeof-pointer-memaccess。这可能会导致代码中出现新警告,这些警告与以前版本的GCC一起干净地编译。
例如,
include string.h
struct A { };
int main(void)
{
A obj;
A* p1 = &obj;
A p2[10];
memset(p1, 0, sizeof(p1)); // error
memset(p1, 0, sizeof(*p1)); // ok, dereferenced
memset(p2, 0, sizeof(p2)); // ok, array
return 0;
}
提供以下诊断: 警告:'void memset(void *,int,size_t)中'sizeof'的参数'call是与目标相同的表达式;你是不是要取消引用它? [-Wsizeof指针-memaccess] memset(p1,0,sizeof(p1)); //错误 ^ 虽然这些警告不会导致编译失败,但通常将-Wall与-Werror结合使用,因此新警告会变成新错误。 要修复,要么重写要使用memcpy,要么取消引用有问题的memset调用中的最后一个参数。*
嗯,在他们的例子中,显然代码是错误的,但在我的情况下,使用snprintf / strncpy,我不明白为什么,我认为这是gcc的错误positif错误。对吗?
感谢您的帮助
答案 0 :(得分:9)
当您传递给函数时,数组会衰减为指向第一个元素的指针。那么你有什么
static inline void toto(char str[3]) {..}
不是数组而是指针。
因此,gcc正确警告。
是否在函数参数中指定大小并不重要:
static inline void toto(char str[3])
和
static inline void toto(char str[])
和
static inline void toto(char *str)
都是等价的。
请阅读此处:what is array decaying?
答案 1 :(得分:4)
test.c的:
#include <stdio.h>
void bar(char foo[1000])
{
printf ("sizeof foo = %d\n", (int)(sizeof foo));
}
int main ()
{
char foo[1000];
bar(foo);
}
运行:
bash $ ./test
4
bash $
这就是原因。
答案 2 :(得分:3)
在函数定义中,参数声明:
static inline void toto(char str[3])
不会将str
声明为数组(C没有数组类型的参数)。相反,它完全等同于:
static inline void toto(char *str)
3
被悄悄忽略。
所以sizeof(str)
与字符串可以容纳的字符数无关,它只是char*
指针的大小。
这是由一条规则引起的,该规则说明用数组类型声明的参数被“调整”为指针类型。这与在大多数上下文中将数组类型的表达式隐式转换(或“衰减”)为指针的规则不同。这两个规则协同工作,使得处理数组的代码看起来像直接处理数组,当它真正使用指向数组元素的指针时。
C数组和指针之间的关系经常令人困惑。我建议阅读comp.lang.c FAQ的第6节;它很好地解释了它。
答案 3 :(得分:2)
static inline void toto(char str[3])
定义了一个可以采用任何大小的数组的函数。 3
被忽略,str
被视为指针(try printf("%d\n", sizeof(str))
:在我的机器上,它打印出64位指针的大小)。在这种情况下,编译器实际上是正确的。
Clang在这里给出了一个有用的警告:
test.c:6:25: warning: sizeof on array function parameter will return size of
'char *' instead of 'char [3]' [-Wsizeof-array-argument]
snprintf(str, sizeof(str), "XX");