Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does a C Compiler know that char** x points to an array?

Tags:

arrays

c

pointers

In C, I've read that char** x and char* x[] mean exactly the same thing. I understand the 2nd example, but I do not understand the 1st example.

To me the first example is saying "pointer to a pointer to a character", but C will see this as "point to a list of pointers to character arrays"?

Would someone be able to explain this to me in layman's terms as I've been having an unusually difficult time grasping it.

EDIT: I admit I worded the first bit as what I thought people would want to hear and not my actual interpretation. I too see it as a pointer to a pointer to a char but my understanding fell when I read the top answer on this question: Difference between char *argv[] and char **argv for the second argument to main()

Which shows that it is being used like a pointer to an array of character pointers when used as an argument vector...

like image 810
Felipe Warrener-Iglesias Avatar asked Mar 02 '18 18:03

Felipe Warrener-Iglesias


2 Answers

Long story short - it doesn't distinguish that. Compiler doesn't know that it points to an array. All it sees is a pointer. The way you have shown(as part of function parameter declaration - passing to the function) char *[] and char ** denotes the same thing. What it is? Pointer to a char*. Nothing more than that.

There is no extra information kept by a compiler that makes it distinguish whether you passed a char* array or a char** because ultimately char* array decays into pointer to first element - which is char**.

Try this, you would understand:-

char c = 'a';
char *pc = &c;
char **ppc = &pc;
f(ppc);

....

void f(char *ppc[]){

}

This won't make compiler complain. Because it is ultimately considered by compiler as char **ppc.

To prove that arrays are not seen by the compiler when it is passed to the function - you can see this quote (which basically says that there is decay and it boils down to pointer to first element. So it sees a pointer that's all) (This by no way give the idea that char** and char*[] are same in all cases because of decaying - it is not)

§6.3.2.1¶3 c11 standard N1570

Except when it is the operand of the sizeof operator, the _Alignof operator, or the unary & operator, or is a string literal used to initialize an array, an expression that has type 'array of type' is converted to an expression with type 'pointer to type' that points to the initial element of the array object and is not an lvalue. If the array object has register storage class, the behavior is undefined.

The edit is been made to clear the misinterpretation that got someone to not appreciate the answer.

like image 58
user2736738 Avatar answered Sep 22 '22 20:09

user2736738


How does a C Compiler know that char** x points to an array?

It doesn't!

To me the first example is saying "pointer to a pointer to a character"

Correct.

but C will see this as "point to a list of pointers to character arrays"?

Also correct.

The trick is that although the language doesn't know how long the list is, a list with just one thing in it is still a list. So it doesn't really matter.1

Given a pointer T* ptr, *ptr will either give you the one object that ptr points to (out of one), or it will give you the first object that ptr points to (out of more than one).

It's only if you start incrementing that pointer (e.g. ptr++, or during access like ptr[152]) that it matters how many objects are actually at the other end. Again, though, it doesn't matter to the language, because that's left up to the programmer to get right.

1. There do exist pointer-to-array types, so it is possible to bring the type system into the discussion and then it does matter. But we are only discussing pointer-to-single-object types (despite the linked-to answer making a big mess of the subject as regards "passing" arrays by value).


If it helps, the opening statement for the top answer on the question you linked to:

Basically, char* argv[] means array of char pointers, whereas char** argv means pointer to a char pointer.

…is wrong. char* argv[] is transparently respelled as char** argv (thanks a lot, C!) so both of them mean literally the same thing.

You should read all the answers under a question, not just one; bmargulies's is much more accurate.

like image 37
Lightness Races in Orbit Avatar answered Sep 23 '22 20:09

Lightness Races in Orbit