4 ms·
I never understood the reasoning behind this, is it that "the asterisk is part of the type, so we group it that way"? That misses the point of the C declaratio
by bigdict 6y ago
I never understood the reasoning behind this, is it that "the asterisk is part of the type, so we group it that way"?
That misses the point of the C declaration syntax: you write an expression that when used on its own will recover the basic type. So the asterisk goes with the symbol name, because that's how you dereference a pointer.
Further, it doesn't work if you want to declare more than one pointer like so:
int* a, b; /* wrong */
int *a, *b; /* correct */
- rootbear 6y agoI think the issue is that programmers want a type "pointer to int", for example, but C doesn't directly provide that type. It has a type, int, with a modifier (asterisk) that can be applied to a declarator to make it a pointer to that type. One way to create a pointer type in C would be to declare it using typedef: typedef int * int_p; then one can write: int_p p, q, r; and declare three pointers to int with perfect clarity, whereas using the C++ style, we'd get: int* p, *q, *r; which is very confusing, or, int* p; int* q; int* r; which is very verbose. I honestly don't know how C++ programmers typically handle this situation. I have seen some code that strikes a middle ground: int * p; which is a little more clear, but doesn't address the multiple declarator situation. So why don't C++ programmers use typedef? I don't know, other than I understand Stroustrup doesn't like it (not without reason). (Edited for formatting and minor clarity corrections.)
- implicit 6y agoMost modern C++ code that I've seen restricts code to declaring a single variable per statement. It's not really a big deal because things are also always introduced at the latest possible position. Each is also typically given an initializer. I'd consider it suspicious if I were to see C++ that declared 3 uninitialized pointers back to back like this. And then you get to the codebases where the authors have chosen to embrace auto and type inference... :)
- 0xffff2 6y agoI handle it by outlawing multiple declaration on a single line. It may be more verbose, but it's much easier to read IMO. This has been a somewhat common rule in my experience.
- kazinator 6y agoThis is not "C++ style"; it's just a poorly considered style perpetrated by coders who are not familiar with the grammar. The C++ syntax is the same as C in this regard: a declaration has specifiers, and then one or more declarators. The exception are function parameters, where you have (at most) one declarator. > why don't C++ programmers use typedef? C++ programmers do use typedef. For instance: typedef std::map<from_this_type, to_this_type> from_to_map; C++ programmers probably use typedef a bit less than they used to, because of features like auto. When a C++ class/struct is declared, its name is introduced into the scope as a type name. Therefore, this C idiom is not required in C++: typedef struct foo { int x } foo; that cuts down some typedefs. If you used a typedef for a C++ class that isn't just a "POD", you have issues, because the typedef name doesn't serve as an alias in all circumstances. typedef class x { x(); } y; y::y() // cannot write x constructor this way { }
- Y_Y 6y agoIt's worth noting that this nice C logic falls apart when you do something like f(int &a); to mean "by reference" instead of what it should be, which is "get the address of a, and that will be an int" which is , of course, nonsense.
- kazinator 6y agoI don't follow. The above is not C. It's a C++ extension over C declaration syntax in such a way that the & is part of the declarator just like * . // Inexcusable trompe l'oeil: int& a, b; // OK; int &a, &b; Here, the mistake may be harder to catch, because the expressions a and b are both of type int, either way. // Intent: b is an alias of a. // Reality: b is a new variable, holding copy of x. int& a = x, b = a; I think what you mean is that the "declaration follows use" principle falls apart for C++ references. That is necessarily true because no operator is required at all to use a C++ reference, whereas the explicit & type construction operator is required in the declarator syntax to denote it. However, it has little to do with the issue that & is part of the declarator and not of the type specifiers. Declaration follows use also falls apart for function pointers in C, because while int (* pf)(int) can be used as result = (* pf)(arg), it is usually just used as result = pf(arg). Declaration follows use also falls apart for the -> notation. A pointer ptr is always being used as ptr->memb, but declared as struct foo *ptr which looks nothing like it. And of course, arrays can be used via pointer syntax, and pointers via array syntax, also breaking declaration follows use. Declaration follows use is only a weak principle used to help newbies get over some hurdles in C declaration syntax.
- optymizer 6y ago"pointer to int" is a type, because 'pointer to' is not a type qualifier like 'const'. You can call it a modifier but you'll quickly start making exceptions for any type that has a modifier to explain away why it's actually a different type with a different size. For example, sizeof(x) takes a type. The type argument for sizeof(int) is different than sizeof(int* ) and the results are different. sizeof(int*[3]) is different as well. These are all different types where pointers change the type. It's not the same type with a pointer modifier, there is no such thing.
- UncleMeat 6y ago> I honestly don't know how C++ programmers typically handle this situation. The verbose one. A few extra lines rarely matters. I think the number of times this has come up in my code base is very very small, maybe a few dozen extra lines across hundreds of thousands.
- sacado2 6y agoA C++ function declaring several uninitialized pointers one after the other is very suspicious anyway. It looks like the programmer is trying to write old-school (pre C99) C code (declaring all variables at the top of the function) in C++. Typedeffing pointers, especially for the sole purpose of "being less verbose" when declaring uninitialized pointers, is a red flag too.
- secondcoming 6y ago> I never understood the reasoning behind this, is it that "the asterisk is part of the type, so we group it that way"? Yes. It just looks better IMO. Now, east-const vs west-const?
- Y_Y 6y agoThis should be mandatory reading for everyone who ever writes code I have too look at or debug.
- 0xffff2 6y agoI'm a C++ guy who prefers `int*`. I also hate multiple declarations on a single line so I just outlaw that entirely so I never have an issue with declaration correctness.
- ramzyo 6y agoThree cheers for pointing out that this boils down to preference. In years programming C in teams and projects of various sizes and criticality, I've never come across a situation where the asterisk position actually made a difference, other than to incite grumbles from those who prefer it whatever which way. I sincerely look forward to a situation where it does make a difference to the maintainability or correctness of code in a way that can't be addressed with other language syntax, or impedes a team's ability to deliver reliable production software against whatever style guide or coding standard they've adopted.
- Ragnarork 6y agoI'm in the same boat, and I'd like to add that I agree that using `int* p, * q, * r;` is not pretty, and could possibly lead to ending up mistakenly with `int* p, q, r;`. But we're in 2020 and we've learned to avoid to declaring stuff without initializing it at the same time to avoid the stupid mistake of using something uninitialized. Interestingly enough, testing with clang shows that uninitialized variables get their warning, but uninitialized raw pointers don't.
- MarekKnapek 6y agoint* a, b; /* wrong */ int *a, *b; /* also wrong */ /* correct */ int* a; int* b;
- drummer 6y agoint* a, b; /* wrong */ int *a, *b; /* also wrong */ /* correct */ int* a; int* b; /* moar correct */ int* a{nullptr}; int* b{nullptr};
- CodeArtisan 6y agoThe choice between ``int p;'' and ``int p;'' is not about right and wrong, but about style and emphasis. C emphasized expressions; declarations were often considered little more than a necessary evil. C++, on the other hand, has a heavy emphasis on types. A ``typical C programmer'' writes ``int p;'' and explains it ``p is what is the int'' emphasizing syntax, and may point to the C (and C++) declaration grammar to argue for the correctness of the style. Indeed, the binds to the name p in the grammar. A ``typical C++ programmer'' writes ``int p;'' and explains it ``p is a pointer to an int'' emphasizing type. Indeed the type of p is int. I clearly prefer that emphasis and see it as important for using the more advanced parts of C++ well. https://www.stroustrup.com/bs_faq2.html#whitespace https://www.stroustrup.com/bs_faq2.html#whitespace
- saagarjha 6y agoHacker News has made your comment fairly difficult to understand ;)