As pointed in the comments, it helps if you consider that in C a declaration is a type followed by a list of names.
In the line
char c = 'a';
c is the name and char is the type.
And when you declare
char *p = &c;
it is a bit strange and leads to confusion. The asterisk has different meanings in C depending on this position:
- it is the operator for multiplication.
- it is also the dereference operator, one that is also called the indirection operator, as if it was not sufficiently confusing.
- in a declaration it indicates a pointer.
We can not blame C, since the language was designed for systems programming and not for teaching, as Pascal was designed for, years later.
Back to the issue, in the line
char *p = &c;
p is the name, and the type is char* as the compiler sometimes tells you in error messages.
So in fact the compiler sees
char* p = &c;
And p is a pointer to a char.
But what do you see in *p? *p means the content of whatever p points to.
Spaceship* p = &some_ship; // *p is Spaceship
int* p = NULL; // *p is an int
char**** p = some_stuff; // *p is char***
In that sense, as you are learning about pointers, keep in mind the relation between the operator & address-of operator, and the operator * indirection operator, as they signal inverse operations. And keep the * near the type in the declaration.
if pc is char**** then
*pc is char***
**pc is char**
***pc is char*
****pc is a single char as stated in the declaration.
&pc is the address of a pointer to a pointer to a pointer to a pointer of a char.
By writing char *p instead of char* p this C idiosyncrasy is exposed: if p is char* then *p is a char. And you can read it wrong if you keep the asterisk far from the type and next to the name...
See this
#include <stdio.h>
int main(void)
{
char c = 'a';
char* p = &c;
printf("c is '%c' at %p, sizeof(c) is %lu\n", c, &c, sizeof(c) );
printf("p is char* at %p, sizeof(p) is %lu\n", p, sizeof(p) );
printf("and in that address we have *p = '%c'\n", *p );
return 0;
}
that shows
so> gcc -o tst -Wall f30.c
so> ./tst
c is 'a' at 0x7fffdfa36d3f, sizeof(c) is 1
p is char* at 0x7fffdfa36d3f, sizeof(p) is 8
and in that address we have *p = 'a'
so>
p = &c;Compiler warnings are useful in a case like this: "chardiffers in levels of indirection fromchar *"*p = &cis a type mismatch. Also, sincepis not initialized, attempting to access*pis undefined behavior.pstores an address, and sincepis not initialized, its value is not a valid address.char *p = &c;, because this will not be a null-terminated string. Most functions acceptingchar*expect a null-terminated string and will result in undefined behavior if that's not what they get.char *paschar* p. The type of p ischar *. Then it's obvious that the next line should bep = &c. But don't write it this way, which will mess you up when you try to put multiple pointers in one line:char *p, *q;char *poverchar* pto chime in :)