我有以下(看似无辜)的代码:
void singleLeftPadZero(char**);
int main () {
char foo[10] = "0";
singleLeftPadZero(foo); // <-- causes warning
singleLeftPadZero(&foo); // <-- same exact warning, but different "note"
}
我从gcc收到的警告是:
警告:传递'singleLeftZeroPad'的参数1不兼容 指针类型
第一个案例的注释是:
注意:预期'char **'但参数类型为'char *'
我理解这意味着我需要将指针传递给指针,但我只是传递一个指针。因此,我添加了&#34;&amp;&#34;我的论点引起了同样的警告,但是这个说明:
注意:预期'char **'但参数类型为'char(*)[10]'
我做了什么看起来修复它是为了创建一个额外的变量:
char* fooPntr = foo;
然后将该地址作为函数参数传递:
singleLeftPadZero(&fooPntr);
但我不确定为什么会有效!
答案 0 :(得分:1)
数组名foo
衰减为char *
,这是一个指向foo
第一个元素的字符指针。它不是char **
,它是指向指向内存位置的字符指针的字符指针。
你的数组是单维的。所以char *
将你的函数原型修改为
void singleLeftPadZero(char*);
当数组名称衰减为指向数组第一个元素的指针时,foo
本身就是一个给出一个地址。所以&foo
表示指向10个元素数组的指针的地址,因此消息argument is of type ‘char (*)[10]’
。
char (*)[10]
表示指向10个元素数组的字符指针。
虽然数组名称衰减为指针,但指针和数组并不相同。看here。
答案 1 :(得分:1)
你错误地认为指针和数组是相同的东西。他们不是。在某些情况下,它们可以以相同的方式使用(这与说“它们是同一个东西”完全不同),而不是其他情况。您的示例位于上下文中,指针和数组是不同的东西,不能像使用它们一样使用。
在第一种情况下,将foo
传递给singleLeftPadZero()
首先执行“数组到指针转换” - foo
是一个十char
的数组,并且转换为char *
类型的指针,其值等于&foo[0]
。 char *
不是char **
,因此会出现关于不兼容类型和注释的警告。
在第二种情况下,将&foo
传递给singleLeftPadZero()
不会进行转换。相反,&foo
的类型为“指向10 char
数组的指针”,或者(与编译器中的注释一致)char (*)[10]
,这与“指向a的指针完全不同”指向char
“的指针(char **
。这些指针类型 - char (*)[10]
和char **
- 不能隐式转换为彼此。
最后一个案例char* fooPntr = foo
实际上是等价的(感谢foo
)char *fooPntr = &foo[0]
的数组到指针的转换。换句话说,fooPntr
的类型为char *
(因为您已经这样声明)并且包含单个char
的地址 - 数组中名为{{1}的第一个字符}}。由于foo
是fooPntr
类型的变量,因此可以评估其地址char *
,并且类型为&fooPntr
。这正是函数char **
接受的内容,因此singleLeftPadZero()
有效。