I have had the recent pleasure to explain pointers to a C programming beginner and stumbled upon the following difficulty. It might not seem like an issue at all if you alre
I would explain that ints are objects, as are floats etc. A pointer is a type of object whose value represents an address in memory ( hence why a pointer defaults to NULL ).
When you first declare a pointer you use the type-pointer-name syntax. It's read as an "integer-pointer called name that can point to the address of any integer object". We only use this syntax during decleration, similar to how we declare an int as 'int num1' but we only use 'num1' when we want to use that variable, not 'int num1'.
int x = 5; // an integer object with a value of 5
int * ptr; // an integer with a value of NULL by default
To make a pointer point to an address of an object we use the '&' symbol which can be read as "the address of".
ptr = &x; // now value is the address of 'x'
As the pointer is only the address of the object, to get the actual value held at that address we must use the '*' symbol which when used before a pointer means "the value at the address pointed to by".
std::cout << *ptr; // print out the value at the address
You can explain briefly that '' is an 'operator' that returns different results with different types of objects. When used with a pointer, the '' operator doesn't mean "multiplied by" anymore.
It helps to draw a diagram showing how a variable has a name and a value and a pointer has an address (the name) and a value and show that the value of the pointer will be the address of the int.
The reason why the shorthand:
int *bar = &foo;
in your example can be confusing is that it's easy to misread it as being equivalent to:
int *bar;
*bar = &foo; // error: use of uninitialized pointer bar!
when it actually means:
int *bar;
bar = &foo;
Written out like this, with the variable declaration and assignment separated, there is no such potential for confusion, and the use ↔ declaration parallelism described in your K&R quote works perfectly:
The first line declares a variable bar
, such that *bar
is an int
.
The second line assigns the address of foo
to bar
, making *bar
(an int
) an alias for foo
(also an int
).
When introducing C pointer syntax to beginners, it may be helpful to initially stick to this style of separating pointer declarations from assignments, and only introduce the combined shorthand syntax (with appropriate warnings about its potential for confusion) once the basic concepts of pointer use in C have been adequately internalized.
If the problem is the syntax, it may be helpful to show equivalent code with template/using.
template<typename T>
using ptr = T*;
This can then be used as
ptr<int> bar = &foo;
After that, compare the normal/C syntax with this C++ only approach. This is also useful for explaining const pointers.
The type of the expression *bar
is int
; thus, the type of the variable (and expression) bar
is int *
. Since the variable has pointer type, its initializer must also have pointer type.
There is an inconsistency between pointer variable initialization and assignment; that's just something that has to be learned the hard way.
You should point out a beginner that * has different meaning in the declaration and the expression. As you know, * in the expression is a unary operator, and * In the declaration is not an operator and just a kind of syntax combining with type to let compiler know that it is a pointer type. it is better to say a beginner, "* has different meaning. For understanding the meaning of *, you should find where * is used"