简体   繁体   English

为什么不能将指向固定大小数组的指针的地址传递给期望指向C中指针的函数?

[英]Why can't I pass the address of a pointer to a fixed size array into a function expecting a pointer to a pointer in C?

I've got the following (seemingly innocent) code: 我有以下(看似无辜的)代码:

void singleLeftPadZero(char**);
int main () {
  char foo[10] = "0";

  singleLeftPadZero(foo); // <-- causes warning
  singleLeftPadZero(&foo); // <-- same exact warning, but different "note"
}

The warning I get from gcc is: 我从gcc得到的警告是:

warning: passing argument 1 of 'singleLeftZeroPad' from incompatible pointer type 警告:从不兼容的指针类型传递'singleLeftZeroPad'的参数1

And the note for the first case is: 第一种情况的注释是:

note: expected 'char **' but argument is of type 'char *' 注意:预期为'char **',但参数的类型为'char *'

I understood this to mean that I needed to pass a pointer to a pointer, but I was just passing a pointer. 我理解这意味着我需要将一个指针传递给一个指针,但是我只是传递一个指针。 Hence, I added the "&" to my argument, which resulted in the same warning but this note: 因此,我在参数中添加了“&”,这导致了同样的警告,但以下注意事项:

note: expected 'char **' but argument is of type 'char (*)[10]' 注意:预期为'char **',但参数的类型为'char(*)[10]'

What I did which looks like it fixed it was to create an extra variable: char* fooPntr = foo; 我所做的看起来很固定的操作是创建一个额外的变量: char* fooPntr = foo; And then to pass the address of that as the function argument: singleLeftPadZero(&fooPntr); 然后将其地址作为函数参数传递: singleLeftPadZero(&fooPntr); But I'm not sure why this works! 但是我不确定为什么这样!

The array name foo decays to a char * , which is a character pointer pointing to the first element of foo . 数组名称foo衰减为char * ,这是指向foo第一个元素的字符指针。 It is not a char ** which is a character pointer pointing to a character pointer pointing to a memory location. 它不是char ** ,它是指向存储位置的字符指针的字符指针。

You array is single dimensional. 您的数组是一维的。 So it's char * Modify your function prototype to 就是char *将您的函数原型修改为

void singleLeftPadZero(char*);

As array name decays to a pointer to first element of array, foo itself is a gives an address. 由于数组名称衰减为指向数组第一个元素的指针,因此foo本身是一个给出地址的地址。 So &foo means address of a pointer pointing to an array of 10 elements hence the message argument is of type 'char (*)[10]' . 因此&foo表示指向10个元素的数组的指针的地址,因此message argument is of type 'char (*)[10]'

char (*)[10] means a character pointer to an array of 10 elements. char (*)[10]表示指向10个元素的数组的字符指针。

Though an array name decays into a pointer, a pointer and an array are not the same. 尽管数组名称会变成一个指针,但是指针和数组并不相同。 Look here . 这里

You're making the mistake of believing a pointer and an array are the same things. 您错误地认为指针和数组是同一回事。 They are not. 他们不是。 They can be used in the same way (which is completely different from saying "they are the same thing") in some contexts but not others. 在某些情况下可以相同的方式使用它们(这与说“他们是同一件事”完全不同),而在其他情况下则不能。 Your examples are in contexts in which pointers and arrays are different things, and cannot be used as if they are the same thing. 您的示例在上下文中,其中的指针和数组是不同的事物,并且不能像它们是同一事物那样使用。

In your first case, passing foo to singleLeftPadZero() works by first performing an "array to pointer conversion" - foo is an array of ten char , and is converted to a pointer of type char * with value equal to &foo[0] . 在第一种情况下,传递foosingleLeftPadZero()通过首先执行“阵列到指针转换”作品- foo是10块的阵列char ,并转换成类型的指针char *具有值等于&foo[0] A char * is not a char ** , hence the warning about incompatible type and the note. char *不是char ** ,因此有关类型和注释不兼容的警告。

In the second case, passing &foo to singleLeftPadZero() doesn't do a conversion. 在第二种情况下,将&foo传递给singleLeftPadZero()不会进行转换。 Instead &foo is of type "pointer to array of 10 char ", or (consistent with the note from your compiler) char (*)[10] , which is a completely different thing from "a pointer to a pointer to a char " (which is char ** . These pointer types - char (*)[10] and char ** - are not implicitly convertible to each other. 相反, &foo的类型为“指向10个char数组的指针”,或者(与编译器的注释一致) char (*)[10] ,这与“指向char的指针的指针”完全不同(这是char ** 。这些指针类型- char (*)[10]char ** -不是隐式转换到彼此。

The last case char* fooPntr = foo is actually equivalent (thanks to the array to pointer conversion of foo ) char *fooPntr = &foo[0] . 最后一种情况下char* fooPntr = foo实际上相当于(感谢数组的指针转换foochar *fooPntr = &foo[0] In other words, fooPntr is of type char * (since you've declared it that way) and contains the address of a single char - the first character in the array named foo . 换句话说, fooPntr的类型为char * (因为您已经这样声明了),并且包含单个char的地址-名为foo的数组中的第一个字符。 Since fooPntr is a variable of type char * , its address &fooPntr can be evaluated, and has type char ** . 由于fooPntrchar *类型的变量,因此可以评估其地址&fooPntr并具有char **类型。 Which is an exactly what the function singleLeftPadZero() accepts, so singleLeftPadZero(&fooPntr) is valid. 这正是singleLeftPadZero()接受的功能,因此singleLeftPadZero(&fooPntr)有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM