It happens on occasion, in the programming world, that bad coding conventions become the norm. Consider for instance the following two lines of code:
int* pointer1; int *pointer2;
Both lines are equivalent as far as the compiler is concerned, but when a human being parses these lines intuitively, they say slightly different things. The first line parses as “create a variable called ‘pointer1‘ that is of type ‘int*‘”, while the second line comes across as “create a variable called ‘*pointer2‘ that is of type ‘int‘”. One of these interpretations matches the semantics of the language and what the compiler actually does when it processes this code, and the other does not. If you are familiar with pointer types, then you know which is which, and if not then I’ll just tell you that it’s the first version. The first line of code is the correct way to declare a pointer.
Sadly, current coding conventions actually favor the second line. The wikipedia page on this subject even attempts to justify this backwards way of declaring a pointer with the explanation that “when the program dereferences the pointer, it has the type of the object to which it points”. That may hold true in simple cases such as the above example, but now consider the following:
Am I declaring here a function such that “when the program dereferences [it], it has the type [int]”? No. Even if that made the slightest bit of sense semantically given that trying to dereference a function with the unary ‘*‘ operator is incorrect, it is not what I’m doing. I’m declaring a function that has a return type of ‘int*‘. Not a return type of ‘magic value that if I put a star in front of it will give me an int‘. If we move to a language with slightly different syntax, like Objective-C, the problem with the convention becomes even more pronounced. For instance:
- (NSString*) toString; //this is a valid function declaration in Objective-C - (NSString) *toString2; //this will make the Objective-C compiler very, very sad - (void) functionWithAString: (NSString*) string; //also valid - (void) functionWithAString2: (NSString) *string; //not a chance
Objective-C does an excellent job of highlighting the problem with the standard convention because in Objective-C the return and parameter types in function declarations must be enclosed within parenthesis. And the asterisk must be included in the parenthesis with the name of the type, because it is part of the type of the object, and not part of its name as the standard convention tries to imply.
And that’s the other half of the justification that is used to defend the standard convention; that by “hiding” the pointer type so that it looks like part of the variable name developers (in particular, novice developers) can use pointer types without having to really understand or think about pointer types. This is bad for a couple of reasons. First off, it’s trying to twist the semantics of the language in a way that is not accurate. And more importantly, it discourages (and/or delays) developers from taking the time to understand what pointer types are and how they work. Yes, pointers can be confusing, but if you’re going to work in a language that includes them then you need to understand how they work. How they really work; not just how a confusing coding convention tries to make it seem like they work.
So at the end of the day, the asterisk character in C and C-like languages is part of the type being declared and not part of its name, and it’s time to start putting it where it belongs; with the type. A bad convention should not be allowed to stand just because it is the convention. Write code that intuitively matches its semantic meaning in the language, not code that is designed to trick people who don’t really understand how pointers work into being able to work with them anyways.
Lastly, and only somewhat tangentally, the following are all examples of very bad coding style, and you should not write code like this no matter where you put your asterisks:
int x, y; //no int *x, y; //bad int* x, y; //not any better int *x, *y; //you get the idea... int* x, *y; int x, *y;
Instead, simply do like so:
int x; int* y;
It’s not like you pay by the newline when you write code. Limit your variable declarations to one-per-line. Trust me, you’ll write more readable code that way.