0

The question is: what is the difference between

char c = 'a';
char *p = &c;

AND

char c = 'a';
char *p;
*p = &c;

The result of execution is very different (the first as expected and the second is compilation error). I have just started "Pointers", so please, be patient about it.

8
  • 7
    For them to be the same, the third line needs to be p = &c; Compiler warnings are useful in a case like this: "char differs in levels of indirection from char *" Commented Aug 30, 2021 at 20:57
  • 3
    *p = &c is a type mismatch. Also, since p is not initialized, attempting to access *p is undefined behavior. p stores an address, and since p is not initialized, its value is not a valid address. Commented Aug 30, 2021 at 21:01
  • 2
    Be careful with char *p = &c;, because this will not be a null-terminated string. Most functions accepting char* expect a null-terminated string and will result in undefined behavior if that's not what they get. Commented Aug 30, 2021 at 21:05
  • 1
    Think of char *p as char* p. The type of p is char *. Then it's obvious that the next line should be p = &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; Commented Aug 30, 2021 at 21:07
  • 2
    I would like to ask people who prefer char *p over char* p to chime in :) Commented Aug 31, 2021 at 0:25

6 Answers 6

3

The * has different meanings when declaring a variable verses assigning an existing variable.

When declaring the variable * means that the variable p is a pointer to a char instead of just a char.

On the other hand in the assignment to an existing variable the * dereferences a pointer. That is rather than working on the pointer the asaignment would work on the location pointed to by the pointer,

So your second example is doubly broken

Firstly it dereferences an uninitialized pointer. Secondly when it tries to make the assignment it has a type mismatch.

Sign up to request clarification or add additional context in comments.

Comments

1

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>

3 Comments

This "explanation" with all the whitespace might work for this very simple case, but it doesn't work for other declarations like int a(int); or int (*b)[5];
This is an "explanation" precisely for the very simple case. As noted by the author, he is starting with "Pointers" :)
when starting to learn something one may be grateful for "all the whitespace" and the so many words.
1

The

char *p = &c;

is initialization of the pointer p with address of variable c, while

*p = &c;

is assignment where the pointer p is dedeferenced and the address of c is written to the address in memory which p is specifying. For your code depending on the context this could be the address 0 (if p is a zero pointer) or some random address in most cases (since p is not initialized).

Comments

1

The first part of code is correct but the second one is not because you tried to assign a value to variable with a different type.

In other words *p and &c are two different types of variables. In order to correct it, you need to write:

p = &c;

Comments

1

C lets you initialize, i.e. declare and assign at the same time. With pointers, it matters whether the * is included or not:

char *p = &c;
^^^^^^^     
   |  ^^^^^^
   |     |
 decl.   |
        ass.

Only p overlaps. What is being assigned to is p, not *p. On two lines:

char *p;
p = &c

p is an address/pointer. But with just *p (or p[0] or p[...]) it is turned into a char. These two sides of a pointer almost overlap in a initialization like above.

Comments

-1

The first is parsed as

(char *) p = & c;

i.e., "a variable p, of type char *, is initialized with the address of c".

the latter

*p = &c;

is parsed as "take the variable p, dereference what it points to, and assign that the address of c". That fails, because what p points to is a char, not a char*.

1 Comment

The syntax for a declaration is a type name followed by declarator list, so your statement is incorrect; it's parsed as type name char with declarator *p and then initializer. C declarations use infix syntax, not prefix as you suggest, the two cases only look the same for extremely simple declarations. Consider char q[5]; vs char[5] q;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.