4 ms·
When I was learning C a couple decades ago, pointer syntax never made any sense to me until something suddenly clicked with “put it directly next to the type na
by inspector-g 6y ago
When I was learning C a couple decades ago, pointer syntax never made any sense to me until something suddenly clicked with “put it directly next to the type name and not next to the variable name”. Ever since then I have not been able to figure out why it is commonly taught next to the variable name.
I mean, short of enabling declarations like:
char *a, *b;
But I have long since found the tradeoff to be worth the syntactic clarity.
- bluejekyll 6y agoI find it to be clear to have the * with the type. Otherwise it can be confused (not by the compiler but the reader) that you are dereferencing the variable a or b.
- _hexley_ 6y agoIn my own projects, I like to put the * on its own, like so: int const * const i; This is nice because you can naturally read the signature from right to left. "i" is a constant pointer to a constant integer. It's a little unconventional, but I think it's a really clear way to convey the types.
- wrs 6y agoThe type of a is char * . Some people (me included) find it clearer to write the type, followed by the variable name. So just as you’d write int a , you’d write char* a . The fly in this ointment is that C type syntax doesn’t want to work that way. It’s designed to make the definition of the variable look like the use of the variable. A clever idea, but unlike nearly every other language, which BTW is why I think you should really use typedefs for any type at all complicated in C. For example, the type-then-variable style falls down if you need to declare an array int foo[4] or a pointer to a function returning a pointer to an int int *(*a)(void) (...right?). So I’m perfectly willing to do it the “C way”, I just find out more readable to do it the other way unless it just won’t work (and then prefer to use typedefs to make it work anyway). Note that this was rethought for Go syntax.
- deleted 6y ago[deleted]
- supplementation 6y ago> Ever since then I have not been able to figure out why it is commonly taught next to the variable name. C does this very cute (read: horrifyingly unintuitive) thing where the type reads how it's used. So "char ⋆a" is written so because "⋆a" is a "char", i.e. pointer declarations mimic dereferencing, and similarly, function pointer declarations mimic function application, and array declarations mimic indexing into the array.
- sergeykish 6y agoI found it much easier to understand than Pascal. It just clicked. Later there was a moment of confusion with "char* a, b". It helped than I've learned by K&R C book. Windows API and code examples are horrific, like another language. https://docs.microsoft.com/en-us/windows/win32/learnwin32/windows-coding-conventions https://docs.microsoft.com/en-us/windows/win32/learnwin32/wi... https://docs.microsoft.com/en-us/windows/win32/learnwin32/managing-application-state- https://docs.microsoft.com/en-us/windows/win32/learnwin32/ma...
- edflsafoiewq 6y agoIt teaches declaration-mirrors-use char *a => *a is a char char a[3] => a[i] is a char char f(char) => f(c) is a char char (*f)(char) => (*f)(c) is a char (short form: f(c))
- TomSwirly 6y agoBut that doesn't mean it's understandable!
- richardwhiuk 6y agoWith the minor problem that `a[3]` isn't valid.
- edflsafoiewq 6y agoDepends how you use it (&a[3], sizeof(a[3])). But its type is still char.
- richardwhiuk 6y agoIIRC, both of those are undefined.
- edflsafoiewq 6y ago&a[3] is allowed, it's a one-past-the-end-of-the-array pointer. &a[4] would be UB (if it were evaluated). sizeof(a[3]) is not evaluating a[3], so it also isn't UB.
- deleted 6y ago[deleted]
- ericbarrett 6y agoThe best argument against this, and for leaving the * by the variable name, is this declaration: char* a, b; Now a has type char * but b is just char. It’s probably not what the author meant and it’s definitely ambiguous even if it was intentional. Better to write: char b, *a; Or, if you meant it this way: char *a, *b; “Well, don’t declare multiple variables on the same line,” you respond. Sure, that’s good advice too. But in mixed, undisciplined, or just old code, it’s an easy trap to fall into.
- saagarjha 6y agoAnother good argument is trying to define a function pointer without typedefs.
- kbenson 6y agoThe question is, why doesn't C make char* a, b; apply the char* type to both? (That is, why didn't they design it that way?) I assume there was some reason originally, but it's made everything a bit more confusing ever since for a lot of people. :/ Edit: Apparently it's so declaration mirrors use. Not a good enough reason IMO. But plenty of languages have warts and bad choices that get brought forth. I'm a Perl dev, so I speak from experience (even if I think it's not nearly as bad as most people make out).
- TomSwirly 6y agoThis is why a lot of C people do one definition per line for any non-trivial variables.
- moth-fuzz 6y agoIn the olden days of C, pointers were not considered types on their own (you cannot have just a pointer, a pointer must point ‘to’ something, grammatically speaking). The type of the object of that declaration is a char. So it’s not really read as ‘I’m declaring a char-pointer called a’, it’s more along the lines of ‘I’m declaring an unnamed char, which will be accessed when one dereferences a’. Hence the * for dereferencing.
- chousuke 6y agoIt's that way because in C "declaration follows usage". In the above, you're declaring the types of * a and * b to be char, making a and b pointers to char. (EDIT: how do you escape * properly inline with other text?)