Reputation: 97
So let's say:
int n = 50;
int *p = &n;
Why do we use *
and not &
in C? What's the key difference between *
and &
?
Upvotes: 4
Views: 761
Reputation: 123478
C declarations follow a convention often described as “declaration mimics use”. The structure of a declaration matches (as closely as possible) the structure of an expression in the code.
For example, let’s say you have a pointer to an int
named p
. To access the value stored in the pointed-to object, we dereference the pointer with the unary *
operator, like so:
printf( "value of what p points to is %d\n", *p );
The expression *p
has type int
, so we declare p
as
int *p;
This conveys that the variable p
has type "pointer to int
", because the combination of p
and the dereference operator *
in the declarator yield an expression of type int
.
And this is primarily why pointers aren't declared using the &
operator in C, because the type of the expression &p
wouldn't be int
.
C++ uses the unary &
operator to declare references, which are not the same thing as pointers:
void foo( int &ref )
{
ref = new_value(); // writes a new value to the actual parameter ref references
}
int main( void )
{
int x = 1;
std::cout << "x before foo = " << x << std::endl;
foo( x );
std::cout << "x after foo = " << x << std::endl;
return 0;
}
References kind of break this system - there's no &ref
expression that has type int
, it just notes that ref
resolves to the same object as some other identifier.
C declarations are made up of two parts - a sequence of declaration specifiers (storage class specifier, type qualifier(s), type specifier(s)) followed by a sequence of (possibly initialized) declarators. Pointer-ness, array-ness, and function-ness are specified in the declarator:
declaration specifiers declarators
| |
+--------------------+----------------+ +--------+--------+
| | | |
static const volatile unsigned long int a[10], *p, f(void);
| | | | | | | |
| | | | | | | +––––––– function declarator
| | | | | | +––––––––––– pointer declarator
| | | | | +––––––––—–––––——–– array declarator
| | | +–––––––+––––––—+
| | | |
| | | +––––––––––––––——–––––––––––— type specifiers
| +––––––+–––––+
| |
| +–––––––––––––––––––––––––––––––––––––––––––– type qualifiers
+–––––––––––––—––––––––––––––––––––––––––––––––––––––––– storage class specifier
This is important - there's no "pointer to" type specifier. The pointerness is specified by the declarator. If you write something like
int* a, b;
it will be parsed as
int (*a), b;
and only a
will be declared as a pointer.
Upvotes: 2
Reputation: 144780
Using *
to declare pointers is mostly a matter of convention, but there is a reason of consistency: the *
in the declaration int *p
means int
is the type of *p
.
It might seem more consistent to write int &p = &n
as p
is initialized to the address of n
but this convention would not hold for double pointers: int **pp
defines pp
as a pointer to a pointer to an int
, yet pp
cannot be initialized with &(&n)
.
Note that int& p = n;
is a valid definition in C++ for a reference to an int
, which is a pointer in disguise. Modifying p
would then modify n
. References are implemented as pointers without the indirection notation.
Upvotes: 9
Reputation: 211610
In C *
in a variable definition means "pointer to". In an expression the &
operator means "address of", while *
operator means "dereference".
So in effect:
int n = 1;
int* p = &n; // Create a pointer and initialize with the address of n
if (*p == 1) {
// This is true when dereferencing the pointer
}
Why not use &
as in int& p
? Mostly because the syntax isn't set up that way.
It's worth noting that in C++ the &
comes back to mean "reference":
int n = 1;
int& r = n;
Note there's no need for any special treatment on the right-hand side, it just figures it out.
Upvotes: 1