Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the asterisk before the variable name, rather than after the type?

They are EXACTLY equivalent. However, in

int *myVariable, myVariable2;

It seems obvious that myVariable has type int*, while myVariable2 has type int. In

int* myVariable, myVariable2;

it may seem obvious that both are of type int*, but that is not correct as myVariable2 has type int.

Therefore, the first programming style is more intuitive.


If you look at it another way, *myVariable is of type int, which makes some sense.


Something nobody has mentioned here so far is that this asterisk is actually the "dereference operator" in C.

*a = 10;

The line above doesn't mean I want to assign 10 to a, it means I want to assign 10 to whatever memory location a points to. And I have never seen anyone writing

* a = 10;

have you? So the dereference operator is pretty much always written without a space. This is probably to distinguish it from a multiplication broken across multiple lines:

x = a * b * c * d
  * e * f * g;

Here *e would be misleading, wouldn't it?

Okay, now what does the following line actually mean:

int *a;

Most people would say:

It means that a is a pointer to an int value.

This is technically correct, most people like to see/read it that way and that is the way how modern C standards would define it (note that language C itself predates all the ANSI and ISO standards). But it's not the only way to look at it. You can also read this line as follows:

The dereferenced value of a is of type int.

So in fact the asterisk in this declaration can also be seen as a dereference operator, which also explains its placement. And that a is a pointer is not really declared at all, it's implicit by the fact, that the only thing you can actually dereference is a pointer.

The C standard only defines two meanings to the * operator:

  • indirection operator
  • multiplication operator

And indirection is just a single meaning, there is no extra meaning for declaring a pointer, there is just indirection, which is what the dereference operation does, it performs an indirect access, so also within a statement like int *a; this is an indirect access (* means indirect access) and thus the second statement above is much closer to the standard than the first one is.


Because the * in that line binds more closely to the variable than to the type:

int* varA, varB; // This is misleading

As @Lundin points out below, const adds even more subtleties to think about. You can entirely sidestep this by declaring one variable per line, which is never ambiguous:

int* varA;
int varB;

The balance between clear code and concise code is hard to strike — a dozen redundant lines of int a; isn't good either. Still, I default to one declaration per line and worry about combining code later.


I'm going to go out on a limb here and say that there is a straight answer to this question, both for variable declarations and for parameter and return types, which is that the asterisk should go next to the name: int *myVariable;. To appreciate why, look at how you declare other types of symbol in C:

int my_function(int arg); for a function;

float my_array[3] for an array.

The general pattern, referred to as declaration follows use, is that the type of a symbol is split up into the part before the name, and the parts around the name, and these parts around the name mimic the syntax you would use to get a value of the type on the left:

int a_return_value = my_function(729);

float an_element = my_array[2];

and: int copy_of_value = *myVariable;.

C++ throws a spanner in the works with references, because the syntax at the point where you use references is identical to that of value types, so you could argue that C++ takes a different approach to C. On the other hand, C++ retains the same behaviour of C in the case of pointers, so references really stand as the odd one out in this respect.


A great guru once said "Read it the way of the compiler, you must."

http://www.drdobbs.com/conversationsa-midsummer-nights-madness/184403835

Granted this was on the topic of const placement, but the same rule applies here.

The compiler reads it as:

int (*a);

not as:

(int*) a;

If you get into the habit of placing the star next to the variable, it will make your declarations easier to read. It also avoids eyesores such as:

int* a[10];

-- Edit --

To explain exactly what I mean when I say it's parsed as int (*a), that means that * binds more tightly to a than it does to int, in very much the manner that in the expression 4 + 3 * 7 3 binds more tightly to 7 than it does to 4 due to the higher precedence of *.

With apologies for the ascii art, a synopsis of the A.S.T. for parsing int *a looks roughly like this:

      Declaration
      /         \
     /           \
Declaration-      Init-
Secifiers       Declarator-
    |             List
    |               |
    |              ...
  "int"             |
                Declarator
                /       \
               /        ...
           Pointer        \
              |        Identifier
              |            |
             "*"           |
                          "a"

As is clearly shown, * binds more tightly to a since their common ancestor is Declarator, while you need to go all the way up the tree to Declaration to find a common ancestor that involves the int.


That's just a matter of preference.

When you read the code, distinguishing between variables and pointers is easier in the second case, but it may lead to confusion when you are putting both variables and pointers of a common type in a single line (which itself is often discouraged by project guidelines, because decreases readability).

I prefer to declare pointers with their corresponding sign next to type name, e.g.

int* pMyPointer;