5 ms·
I was just thinking about pointer syntax today, and if you ask me, there are a lot of problems that could be avoided if language designers took a page out of Gu
by mariodiana 6y ago
I was just thinking about pointer syntax today, and if you ask me, there are a lot of problems that could be avoided if language designers took a page out of Guido van Rossum's book and extend his idea of forced spacing.
Take the first example you've given, and let's just talk about variable declaration:
int* a;
int * a;
int *a;
That's all the same. That's wrong. Obviously, you can write a lexer and parser that doesn't give a crap, but the human mind does. If you think it doesn't, that's only because you've internalized the various cases.
It should be this:
int* a;
The type we're talking about is a pointer to a variable of type int: in other words, "a" is an int-pointer. If you were to create a macro, you'd do something like this:
#define int_ptr int*
Do you see what I'm getting at? The star in this case is a suffix, equivalent (in our minds) to "_ptr". Conceptually, it doesn't belong anywhere else than attached to the type. It's a compound type, conceptually.
Now, take the star being used in a different context:
int b = 10;
int* a = &b;
printf("%d\n", *a);
There, though we see the same character, it's a completely different thing. It's a dereference operator. Conceptually, it belongs attached to the pointer variable it is dereferencing; and since the star is already used in one context as a suffix, here it should be used as a prefix.
This is no good:
printf("%d\n", * a);
It doesn't matter that "this compiles." That's not what this is about.
Many C programmers (and programmers in other languages, even Python) are used to writing things like this:
int c = x*y;
That's wrong. Sure, the lexer and parser don't care. But that makes the language worse, for the human operator. "But it saves space!" Spare me.
The thing with this one example, using the star, is that what we have is the equivalent of a homonym. We have one sign that is actually three different words. Mandating spacing removes the ambiguity you're complaining about.
C is what it is, but if we imagine someone were going to write it today, they should incorporate the above and mandate spacing. For the sake of the humans. "ident type" is not the only solution.
- klyrs 6y ago> It should be this: > int* a; I must disagree... the following sends the wrong message the reader: int* a, b; Though I also agree that dereferencing is best without a space. Perhaps the correct suggestion is to not declare pointers and instances on the same line, but that's a convenience that many seem to enjoy
- tomjupiter 6y agoI think mariodiana is describing a hypothetical language where a and b would both be int-pointers in this case.
- WalterBright 6y agoTo declare two pointers to int in C: int *a, *b; In D: int* a, b; The use of whitespace makes the distinction clear, although the parser doesn't care.
- klyrs 6y agoC is just riddled with mistakes and this one finally gelled with me. Python taught me that whitespace is great for syntax and, in this case, I'm quite convinced that it should be used more firmly in most languages.
- dirtydroog 6y agoI find the opposite, I can't stand it. Give me curly braces over arbitrary indentation any day.
- mhh__ 6y agoI think a better (subjective of course) lesson might be to enforce a style. I have been thinking about making a toy compiler (I wanted to write a borrow checker) that treats bad code as an error, solely aimed at numerical code - I have recently had "Scientific Programming in Python for physics etc." inflicted on me. Slight tangent, but I think if Haskell enforced some kind of whitespace a la Python it would be much more approachable in real codebases (Haskell is usually quite readable if you are just translating mathematics into code but it - to me at least - feels dreadful as a productive language because of the way a lot of functions seem to be dumped onto into the text editor in a lot of the code I have read)
- 6y ago
- ufo 6y agoThe problem in C is more than just the `*`. Consider arrays, where C uses `int xs[];` instead of `int[] xs;`. There is no way to use define to declare an int_array type like you did with int_ptr. (Function types also exibit a similar problem)
- earthboundkid 6y agoA pointer to an int "should" be &int, not int*. That we use *, the dereference operator, to indicate pointers is wrong. * in a type means it's an address, but * in a value means it's not an address. That's nuts! Make it consistent and use & both places. If you need to have a distinction between refs and pointers, it should be that pointers are nullable refs: &int? or some such. Edit: How to escape asterisks in HN?
- saagarjha 6y agoI’ve had luck with not putting something directly after the asterisk.
- earthboundkid 6y agoApparently HN does not have an escape character which seems like a real oversight. :-/
- mariodiana 6y agoI think you may be right, &int would be better than int*. I did not want to stray too far from what C does now, for the sake of argument. I just wanted to say that the ambiguity in C is often because it's so loosey-goosey with whitespace.
- deleted 6y ago[deleted]
- cyphar 6y agoPeople have been arguing about where the asterisk should be for a very long time. The main counter-argument to the construction you used is that multiple variable declaration immediately looks ugly given the current rules of C variable declaration: int* a,* b; // ?? And that's usually why most C style guidelines use int *a, *b; Now, if we treated "int<asterisk>" as the full type name in the syntax then you get a much nicer result: int* a, b; // much nicer! Though that does have its own tradeoffs. But that would require actually changing the C syntax, at which point you might as well make it the postfix syntax: var a, b int*;
- dllthomas 6y agoThere's a perspective that doesn't seem to be noted yet, which is that int *f is declaring that *f will be an int. This perspective addresses why the star belongs with the name, why it's star instead of ampersand, why you need to repeat the star for multiple variables, why the brackets goes after the name for arrays, and it will sort of get you where you need to go with function pointers (although there's an automatic promotion which means things will work at the call site that won't work for the type). This isn't to say alternative constructions mightn't be a better choice in a new language, but it's much more parsimonious when considering C than memorizing a bunch of special cases.
- kevin_thibedeau 6y agoThen someone comes along and typedefs a pointer to hide the "scary" double pointer syntax.
- dllthomas 6y agoI don't think that actually breaks things. A typedef isn't purely syntactic substitution like a macro. If we have typedef float *floatp; then the following compiles: float x, y; floatp xp = &x, yp = &y; while the following does not: float x, y; float* xp = &x, yp = &y; You have defined a new type (which happens to be equivalent to an old type - note that we don't get nominal type-checking from typedefs); the above logic still holds.
- a1369209993 6y agoThere are four possible spacings to consider: foo*bar; // multiplies foo and bar foo* bar; // declares bar as pointer-to-foo foo *bar; // declares *bar as foo (so bar is still a foo*) foo * bar; // multiplies foo and bar These are all unambigous and there are only two semantics between them. You also have: foo* bar,baz; // baz is a pointer foo *bar,baz; // baz is a foo foo *bar,*baz; // baz is pointer again foo* bar,*baz; // baz is now a pointer *to* a pointer This is all obvious - or at worst unambigous - to a person reading the actual code (without trying to correct for the idiosyncracies of a parser), so the language should either match that or spit out a warning about unsupported spacing. > [`int c = x*y;` is] wrong. No, that's unambigously multiplication.
- deleted 6y ago[deleted]