2

I've always put my asterisk like this when creating pointers:

//directly adjacent to the type
int* p = new int();

So i don't confuse a declaration with a dererefence. But then I learned this:

//p is a pointer, q is an int
int* p, q;

Which is misleading to me, so I began putting the asterisk next the variable, not the type. However, this got me thinking. Why did they design it in this way? It's probably terrible to think of it in this manner, but I always thought of the pointer as part of the type. Like, its not a pointer to an int, its an int pointer. I know its not actually like that, but it has always flowed better in my mind. And what really got me thinking is, why the brackets go:

//after the variable
int p[1];

tldr; Why does the asterisk go in front of the variable, but the brackets behind

BWG
  • 2,238
  • 1
  • 20
  • 32
  • 1
    Are you curious about the motivations of the the language designers? – bitmask Jan 17 '14 at 01:26
  • Yes, that is what I am curious about – BWG Jan 17 '14 at 01:27
  • 2
    btw - you demonstrate why stacking variable declarations on one statement is a bad idea – pm100 Jan 17 '14 at 01:28
  • @BWG Then I'm not sure who can answer that. Ritchie himself is dead, and who knows what he was thinking when he created C? – Dennis Meng Jan 17 '14 at 01:28
  • @pm100 I never really do it. But in the rare case I do, I don't want to have my asterisk placement inconsistent with the rest of my code. – BWG Jan 17 '14 at 01:29
  • @BWG: I once asked such a history question and it was booed out of the room and closed as off topic. Best of luck, though. – bitmask Jan 17 '14 at 01:31
  • You can unconfuse stacked variable declarations with a `typedef` such as `typedef int *PINT;` after which `PINT p,q;` means what you'd expect. That is especially handy with a complex type like `typedef int (*PFUNC)(int);` allowing you to make a table of functions with a clear declaration: `PFUNC maps[3] = {mapa, mapb, mapc};` as long as the functions definitions are in scope and match the prototype. – RBerteig Jan 17 '14 at 01:41

4 Answers4

5

The C syntax for declarations uses a model of “Show us how you would use something and tell us what type that is.”

Thus, if x is an int, we start with x and then say it is an int: int x;.

If x is a pointer to an int, then we would use *x to get an int, so we say int *x;.

If x is a function that returns an int, then we would use it as x() to get an int, so we say that is an int: int x();.

One reason for using this model is that it mostly uses the grammar you have already built for expressions: The body of the declaration gets parsed in the same way as expressions, and then you just tack on the type. If you do not use the same model, then you have to invent more grammar for declaring types.

This model makes declarations such as int *x, y; perfectly clear: Both *x and y have type int.

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • VERY interesting. I wish I could accept multiple answers, all are very telling. This design makes a lot of sense, though I would prefer it the other way. After all, how often does one have to declare different storage types (I think thats what its called) on the same type on the same line? – BWG Jan 17 '14 at 01:59
  • Not all that uncommonly, actually. A single declaration line may be used for a complex multilayered type and for the simpler subtypes that are extracted from it. Of course Best Practice is actually to use typedefs to build up anything really complicated in stages, which gives you the intermediate typedefs as a free bonus. – keshlam Jan 17 '14 at 02:20
  • BTW, good job of illustrating that relationship, Eric. I mentioned it in passing, but you've called it out and made it clearer. – keshlam Jan 17 '14 at 02:21
  • I hate this design philosophy, but I'm glad someone explained it as a general rule. +1 – ApproachingDarknessFish Jan 17 '14 at 02:38
4

The int* style in C was developed relatively late, and I can't really recommend it.

Yes, it's expressive in the simple case. But it rapidly becomes confusing either in multiple declarations or when the declaration is more complex and involves multiple layers of addressing operations.

In C, I would stick with the older convention of applying the addressing operations to the variable name. Among other things, that actually is expressive; the declaration directly mirrors the operations needed to yield the type. That is, if the declaration is int *foo[10], then the expression *foo[3] will have the type int.

To answer your tl;dr ... The brackets going after the variable was established in other languages long before C, and there was no reason to change it. The asterisk going before... I think that's a "flip a coin" decision, and the answer is "for the same reason unary * was used to mean "value pointed to by..." at all; they needed the operation, they grabbed something that didn't conflict with what other characters were being used for, and once they made that decision they couldn't change it without creating a new incompatible language.

It is what it is because that's what C is, unsatisfying as that answer may be.

(Personally, I've always wondered why they didn't use @, and wonder whether that was due to the near religious argument over whether @ most correctly means "at" or "each".)

keshlam
  • 7,931
  • 2
  • 19
  • 33
  • Interesting. I used a (very simple) language for a while, in which the syntax for accessing memory was `{address}`, and I fell in love with that style, because it made so much sense to me. Now all this stuff with "incriment the pointer by the size of the element it points to" really annoys me, because it obfuscates what is actually happening. I guess you have to find that right balance between low and high level. – BWG Jan 17 '14 at 01:54
  • 2
    Yep, it's a balancing act. The terseness of the C syntax does permit some really clever idioms, but also permits some really obscure/bad coding. There's a reason C used to be one of the languages commonly used in obfuscated-code contests. It's a sharp knife; handle with care but you'll get used to it. – keshlam Jan 17 '14 at 02:18
  • Of course C couldn't use the `{address}` syntax, since the curly braces were already being used for block statements. ASCII only has so many punctuation characters, and C was arguably starting to run out... – keshlam Jan 17 '14 at 02:24
0

i suspect that [] was chosen because that's common math notation for indexing

why *x was chosen to mean 'what x points at' is not obvious. But putting the * after 'x' would obviously not works given that * means multiply.

cobol would be better :-)

move what x points to to y
pm100
  • 48,078
  • 23
  • 82
  • 145
  • is that actual cobol syntax? pretty dang verbose – BWG Jan 17 '14 at 01:35
  • Cobol _is_ verbose. It was designed to be a programming language that non-programming managers would feel comfortable looking at. C was designed for terseness and expressiveness, but not for readability... which is why it's especially important for C programmers to be careful formatting and documenting their code. – keshlam Jan 17 '14 at 01:50
  • @BWG no, its a joke. But as keshlam says, cobol is very verbose. It was announced as 'an end to programming, business people can just write their requirements in plain English', ha ha. Typical cobol statement is 'multiply itemprice by numberordered giving ordertotal' – pm100 Jan 17 '14 at 01:58
  • @pm100 neat. Would that equate to something like `ordertotal = itemprice * numberordered`? – BWG Jan 17 '14 at 02:01
  • For the "proper" COBOL experience, you have to shout everything since COBOL predates the existence of lower case on punched cards. And it is *verbose*. See this sample at [RosettaCode](http://rosettacode.org/wiki/Rosetta_Code) for adding A and B and printing the result: [...`ADD A TO B GIVING A-B-SUM` ...](http://rosettacode.org/wiki/A%2BB#COBOL) – RBerteig Jan 17 '14 at 02:02
0

See How do you read C declarations? for more info.

That article links to the cdecl utility (man page at http://gd.tuwien.ac.at/linuxcommand.org/man_pages/cdecl1.html , you'll need to search for the actual utility) which I used to use to understand more complex declarations.

Community
  • 1
  • 1
Eric
  • 2,115
  • 2
  • 20
  • 29