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

Viewed 79669

Why do most C programmers name variables like this:

int *myVariable;

rather than like this:

int* myVariable;

Both are valid. It seems to me that the asterisk is a part of the type, not a part of the variable name. Can anyone explain this logic?

12 Answers

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.

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.

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;

People who prefer int* x; are trying to force their code into a fictional world where the type is on the left and the identifier (name) is on the right.

I say "fictional" because:

In C and C++, in the general case, the declared identifier is surrounded by the type information.

That may sound crazy, but you know it to be true. Here are some examples:

  • int main(int argc, char *argv[]) means "main is a function that takes an int and an array of pointers to char and returns an int." In other words, most of the type information is on the right. Some people think function declarations don't count because they're somehow "special." OK, let's try a variable.

  • void (*fn)(int) means fn is a pointer to a function that takes an int and returns nothing.

  • int a[10] declares 'a' as an array of 10 ints.

  • pixel bitmap[height][width].

  • Clearly, I've cherry-picked examples that have a lot of type info on the right to make my point. There are lots of declarations where most--if not all--of the type is on the left, like struct { int x; int y; } center.

This declaration syntax grew out of K&R's desire to have declarations reflect the usage. Reading simple declarations is intuitive, and reading more complex ones can be mastered by learning the right-left-right rule (sometimes call the spiral rule or just the right-left rule).

C is simple enough that many C programmers embrace this style and write simple declarations as int *p.

In C++, the syntax got a little more complex (with classes, references, templates, enum classes), and, as a reaction to that complexity, you'll see more effort into separating the type from the identifier in many declarations. In other words, you might see see more of int* p-style declarations if you check out a large swath of C++ code.

In either language, you can always have the type on the left side of variable declarations by (1) never declaring multiple variables in the same statement, and (2) making use of typedefs (or alias declarations, which, ironically, put the alias identifiers to the left of types). For example:

typedef int array_of_10_ints[10];
array_of_10_ints a;

A lot of the arguments in this topic are plain subjective and the argument about "the star binds to the variable name" is naive. Here's a few arguments that aren't just opinions:


The forgotten pointer type qualifiers

Formally, the "star" neither belongs to the type nor to the variable name, it is part of its own grammatical item named pointer. The formal C syntax (ISO 9899:2018) is:

(6.7) declaration:
declaration-specifiers init-declarator-listopt ;

Where declaration-specifiers contains the type (and storage), and the init-declarator-list contains the pointer and the variable name. Which we see if we dissect this declarator list syntax further:

(6.7.6) declarator:
pointeropt direct-declarator
...
(6.7.6) pointer:
* type-qualifier-listopt
* type-qualifier-listopt pointer

Where a declarator is the whole declaration, a direct-declarator is the identifier (variable name), and a pointer is the star followed by an optional type qualifier list belonging to the pointer itself.

What makes the various style arguments about "the star belongs to the variable" inconsistent, is that they have forgotten about these pointer type qualifiers. int* const x, int *const x or int*const x?

Consider int *const a, b;, what are the types of a and b? Not so obvious that "the star belongs to the variable" any longer. Rather, one would start to ponder where the const belongs to.

You can definitely make a sound argument that the star belongs to the pointer type qualifier, but not much beyond that.

The type qualifier list for the pointer can cause problems for those using the int *a style. Those who use pointers inside a typedef (which we shouldn't, very bad practice!) and think "the star belongs to the variable name" tend to write this very subtle bug:

    /*** bad code, don't do this ***/
    typedef int *bad_idea_t; 
    ...
    void func (const bad_idea_t *foo);

This compiles cleanly. Now you might think the code is made const correct. Not so! This code is accidentally a faked const correctness.

The type of foo is actually int*const* - the outer most pointer was made read-only, not the pointed at data. So inside this function we can do **foo = n; and it will change the variable value in the caller.

This is because in the expression const bad_idea_t *foo, the * does not belong to the variable name here! In pseudo code, this parameter declaration is to be read as const (bad_idea_t *) foo and not as (const bad_idea_t) *foo. The star belongs to the hidden pointer type in this case - the type is a pointer and a const-qualified pointer is written as *const.

But then the root of the problem in the above example is the practice of hiding pointers behind a typedef and not the * style.


Regarding declaration of multiple variables on a single line

Declaring multiple variables on a single line is widely recognized as bad practice1). CERT-C sums it up nicely as:

DCL04-C. Do not declare more than one variable per declaration

Just reading the English, then common sense agrees that a declaration should be one declaration.

And it doesn't matter if the variables are pointers or not. Declaring each variable on a single line makes the code clearer in almost every case.

So the argument about the programmer getting confused over int* a, b is bad. The root of the problem is the use of multiple declarators, not the placement of the *. Regardless of style, you should be writing this instead:

    int* a; // or int *a
    int b;

Another sound but subjective argument would be that given int* a the type of a is without question int* and so the star belongs with the type qualifier.

But basically my conclusion is that many of the arguments posted here are just subjective and naive. You can't really make a valid argument for either style - it is truly a matter of subjective personal preference.


1) CERT-C DCL04-C.

Because it makes more sense when you have declarations like:

int *a, *b;

When you initialize and assign a variable in one statement, e.g.

int *a = xyz;

you assign the value of xyz to a, not to *a. This makes

int* a = xyz;

a more consistent notation.

Related