Pointers in C: why is the * needed in *address_of_x = &x when getting the address of x?

Viewed 174

Suppose we have the following code, which takes x, stores the value 4 in it, then stores the address of x in a pointer variable:

int x = 4;
int *address_of_x = &x;

What is the purpose of the * in int *address_of_x? I understand * to be used for dereferencing a pointer - it takes an address and tells you what's stored there. But if an address is being stored, then what are we dereferencing? Or are we not dereferencing anything at all? Why isn't it written as:

int address_of_x = &x;
7 Answers

That's the definition of a pointer, the type for address_of_x variable is int *, a pointer to int. There's no "dereference" happening there.

Why isn't it written as:

   int address_of_x = &x;

Well, two things

  • C is a strongly typed language.
  • the variable names do not carry any connection with their type

In an expression, the * is the dereference operator. In a declaration (which you have here), it's part of the syntax of a pointer declarator. You're declaring address_of_x to be a pointer to int rather than just an int.

The idea that was behind this syntax is that declarations and usage of identifiers should look similar (you typically use a pointer by dereferencing it) for convenience.

Also note that the * is needed for every identifier declared as a pointer, even if you declare multiple identifiers in a single declaration, like this:

int *a, *b;

If you write

int *a, b;

instead, b would not be a pointer. In general, it's best practice to avoid declaring more than one identifier per declaration, though.

int *address_of_x = &x; isn't an assignment. int *address_of_x = &x; is a declaration (int *address_of_x) with initialization (= &x) (note that in pre-historic C, initializations (as opposed to assignments) were done without the =, which made them even more distinct from assignments).

Declarations in C mirror usage. int *address_of_x declares that *address_of_x is of type int, ergo address_of_x is of type pointer to int. The = &x part then initializes this pointer to int to &x (address of x).

* in int *address_of_x = &x; is not de-referencing @Eugene Sh.
It is part of the type declaration: pointer to int.

int x = 4;
int *address_of_x = &x;

same as

int x = 4;          // declare x as int
int *address_of_x;  // declare address_of_x as pointer to int
address_of_x = &x;  // Assign the address of x to address_of_x

Why isn't it written as: int address_of_x = &x;

&x is not an int. &x is an int *, a pointer (or address). A pointer is not an integer.

Simple answer: The asterisk in a variable declaration or definition statement is NOT a dereference operator. Instead it's a modifier.

In the given context, an asterisk means "Define the mext identifier as a pointer to the base type".

You surely won't ask why [10] doesn't mean "take the 10th element of the array" in int a[10]. Well, so-so. The brackets here also aren't the bracket operator, for exactly the same reason.

Why isn't it written as:

   int address_of_x = &x;

The compiler never tries to interpret the literal meaning of identifiers. It only looks for modifiers when determining the type of an iddentifier in a declaration statement.

i.e., this code will not work as what it looks like:

int *not_a_pointer, not_an_array[10];
float a_character;

int *address_of_x = &x; declares a variable of type "pointer to int" (int *address_of_x) and then initializes it with the address of x (= &x).

So this * is not the dereferencing but is part of the declaration.

These two snippets are functionally the same:

int *address_of_x = &x;

and

int *address_of_x;
address_of_x = &x;

In the first case you defined and initialised the pointer all in one statement, but it can look like the wrong syntax. In the second example the definition and the value assignment are separate statements, and the code is clearer.

There is no dereferencing (yet).

Related