snprintf错误.sizeof的参数与destination相同

ram*_*one 13 c printf gcc

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;
}
Run Code Online (Sandbox Code Playgroud)

这是gcc错误

错误:'snprintf'调用中'sizeof'的参数与目标的表达式相同; 你的意思是提供一个明确的长度?

注意:我使用-Wall -Werror标志将警告转换为错误.

这里有类似的东西 在评论中,有人回答了这个问题

"对于固定长度缓冲区,我通常使用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]"

在gcc 4.8文档中,他们正在讨论这个问题:他们说:

-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;
}
Run Code Online (Sandbox Code Playgroud)

提供以下诊断:警告:'void memset(void*,int,size_t)'调用中'sizeof'的参数与目标的表达式相同; 你是不是要取消引用它?[-Wsizeof-pointer-memaccess] memset(p1,0,sizeof(p1)); // error ^虽然这些警告不会导致编译失败,但是-Wall经常与-Werror一起使用,因此新警告会变成新的错误.要修复,要么重写以使用memcpy,要么取消引用有问题的memset调用中的最后一个参数.*

好吧,在他们的例子中,显然代码是错误的,但在我的情况下,使用snprintf/strncpy,我不明白为什么,我认为这是gcc的错误positif错误.对 ?

谢谢你的帮助

P.P*_*.P. 9

传递给函数时,数组会衰减为指向第一个元素的指针.那么你有什么

static inline void toto(char str[3]) {..}

不是数组而是指针.

因此,gcc正确警告.

是否在函数参数中指定大小无关紧要:

static inline void toto(char str[3])
Run Code Online (Sandbox Code Playgroud)

static inline void toto(char str[])
Run Code Online (Sandbox Code Playgroud)

static inline void toto(char *str)
Run Code Online (Sandbox Code Playgroud)

都是等价的.

在这里阅读:什么是阵列衰减?


n. *_* m. 6

测试.c:

#include <stdio.h>

void bar(char foo[1000])
{
    printf ("sizeof foo = %d\n", (int)(sizeof foo));
}

int main ()
{
    char foo[1000];
    bar(foo);
}
Run Code Online (Sandbox Code Playgroud)

跑步:

bash $ ./test
4
bash $
Run Code Online (Sandbox Code Playgroud)

这就是为什么。