Why is p = &a;
and *p = a
different?
p = &a
stores the address of a
into p
.
*p = a
stores the value of a
into the thing p
points to.
After writing p = &a
, the following conditions are true:
p == &a; // int * == int *
*p == a; // int == int
and the statement
*p = 5;
is exactly equivalent to writing
a = 5;
The expression *p
basically acts as an alias for the variable a
.
In your code, the line
*p = a;
gave you a segfault because p
had not yet been assigned to point to a writable location. Unless explicitly initialized, the contents of a local variable1 are indeterminate — it could be anything.
When int* p = &a;
is declared, does p = &a
, not *p = &a
?
In a declaration the *
is only there to indicate type; it does not dereference p
, any more than int a[N];
indexes into a
or void f(void)
calls f
. So the declaration initializes p
with the result of the expression &a
(which has type int *
).
Declarations in C are composed of two main sections — a sequence of declaration specifiers followed by a comma-separated list of declarators.
Declaration specifiers include type specifiers (int
, char
, float
), type qualifiers (const
, volatile
), storage class specifiers (auto
, static
, register
), and a few others.
Declarators contain the name of the thing being declared, along with information about that thing's array-ness, function-ness, and/or pointer-ness. In the declaration
unsigned long a[N], *p, f(void);
the declaration specifiers are unsigned long
and the declarators are a[N]
, *p
, and f(void)
. The types of a
, p
, and f
are specified by the combinations of the declaration specifiers and declarators, so the type of a
is "N-element array of unsigned long
, the type of p
is "pointer to unsigned long
", and the type of f
is "function taking no parameters and returning unsigned long
".
Remember that in a declaration the *
operator is always bound to the declarator, not the type specifier. The declaration
T* p; // for any type T
is always parsed as
T (*p);
meaning if you write a declaration like
T* p, q;
only p
will be declared as a pointer; q
will be declared as a regular T
. If both need to be declared as pointers, you'd write
T *p, *q;
- Strictly speaking, we mean something with
auto
storage duration; declared within a block without the static
keyword.