0

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:

warning: passing argument 1 of ‘singleLeftZeroPad’ from incompatible pointer type

And the note for the first case is:

note: expected ‘char **’ but argument is of type ‘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]’

What I did which looks like it fixed it was to create an extra variable: char* fooPntr = foo; And then to pass the address of that as the function argument: singleLeftPadZero(&fooPntr); But I'm not sure why this works!

papiro
  • 2,158
  • 1
  • 20
  • 29

2 Answers2

1

The array name foo decays to a char *, which is a character pointer pointing to the first element of foo. It is not a char ** which is a character pointer pointing to a character pointer pointing to a memory location.

You array is single dimensional. So it's char * Modify your function prototype to

void singleLeftPadZero(char*);

As array name decays to a pointer to first element of array, foo itself is a gives an address. So &foo means address of a pointer pointing to an array of 10 elements hence the message argument is of type ‘char (*)[10]’.

char (*)[10] means a character pointer to an array of 10 elements.

Though an array name decays into a pointer, a pointer and an array are not the same. Look here.

J...S
  • 5,079
  • 1
  • 20
  • 35
1

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]. A char * is not a char **, hence the warning about incompatible type and the note.

In the second case, passing &foo to singleLeftPadZero() doesn't do a conversion. 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.

The last case char* fooPntr = foo is actually equivalent (thanks to the array to pointer conversion of foo) char *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. Since fooPntr is a variable of type char *, its address &fooPntr can be evaluated, and has type char **. Which is an exactly what the function singleLeftPadZero() accepts, so singleLeftPadZero(&fooPntr) is valid.

Peter
  • 35,646
  • 4
  • 32
  • 74