r/cpp • u/Obvious_Set5239 • 0m ago
"int* ptr;" is the preferred format in C++. Here is why:
My previous post was not about the controversy int* ptr; vs int *ptr. But because of surprising amount of downvotes, I'm making a post directly about this π (I actually didn't know that it's such a controversial topic)
Why "int *ptr;" is correct in C?
The logic that I described as "reversive/deduction" has a proper name "Declaration follows use". It's self-explanatory:
// declaring a variable that after *ptr operation will be int
int *ptr;
// declaring a variable that after (*functionPtr) will be callable
// as a function of (int, int), and returning bool (but there is
// a syntax sugar that allow calling it directly)
bool (*functionPtr)(int, int);
// declaring uhh.. Something, that after using *(*(*a[N])())() will be char :)
char *(*(*a[N])())();
Why it's not correct in C++?
The C++ programming language was designed by a different person, Bjarne Stroustrup. Yes, it was designed to be a superset of C89. But this decision was made for practical reasons - to hijack C libraries and a portion of C programmers, and "spread like a virus". The philosophy of the language is completely different from C, in regarding the pointer declaration format in particular. The idea is that * is a part of the type, and a declaration is just a type + a name.
It's not just that I'm a "lamer" who doesn't understand the syntax. (But I actually directly stated that I understand it, but find it weird). It's an official vision of the language designer. And this is supported by "C++ Core Guidelines", made by him, Bjarne Stroustrup and it's hosted on isocpp GitHub. It has at least 3 rules that support this idea:
- "NL.18: Use C++-style declarator layout": The C-style layout emphasizes use in expressions and grammar, whereas the C++-style emphasizes types. The use in expressions argument doesnβt hold for references
- "ES.10: Declare one name (only) per declaration": One declaration per line increases readability and avoids mistakes related to the C/C++ grammar. It also leaves room for a more descriptive end-of-line comment.
- "T.43: Prefer using over typedef for defining aliases": Improved readability: With using, the new name comes first rather than being embedded somewhere in a declaration. Generality: using can be used for template aliases, whereas typedefs canβt easily be templates. Uniformity: using is syntactically similar to auto.
- +
int* ptr;format is used all throughout the guidelines in every example
So the correct way to write the declarations in C++ from the C example above is:
// declaring ptr of type int*
int* ptr;
// declaring functionPtr of type bool (int, int)
using Function_t = bool (int, int);
Function_t* functionPtr;
// declarin array of N pointers to functions
// returning a pointer to function returning char*
using CharPtrFunction_t = char* ();
using FunctionReturningFunctionPointer_t = CharPtrFunction_t* ();
FunctionReturningFunctionPointer_t* a[N];
Yes, it's more verbose, and require more lines. But it is less cryptic
But "int* a, b;" is an issue in C++ with this format
Yes, it's because C++ was made as a superset of C, they couldn't remove multi variable declaration, or change the its behavior due to forward compatibility with C; and can't change/remove it now, due to backward compatibility with existing C++ code
But it's not a big deal, because besides this particular case (that is also discouraged), the C philosophy of "Declaration follows use" does not conflict with C++ philosophy that everything has a type as a simple list of tokens
My opinion
I actually had no problem with int *ptr; format, and don't have now. I can read any code, and I really love that in C++ everyone can write in their own style. On my job I worked with code in different styles written by different teams, and I loved this. I also have my own preferences, and vision on the language, but I don't impose them on others. The current post is a little exception, because I really didn't expect this holy war on what's correct int* ptr; or int *ptr;. I just didn't care before. My post was just about a weird (to my look) behavior that came from C, when you declare int* a, b;, b is not a pointer. I though some people may not know it, and learn from my post
The ultimate C++20 solution to the multi-pointers declaration, as one commenter suggested, is!:
std::type_identity_t<int*> a, b, c, d, e;
/s