i remember an online argument on a forum like 15 years ago where one set of people would say "each to their own" and the other would say "to each their own" and remarkably both sides were able to explain to the other why the syntax made sense to them. there were posts like "oh, you mean each person to their own preference!" i often think of it when there's some nomenclature thing which basically doesn't matter but both sides seem unable to see where the other is coming from

anyway, with this in mind, can someone explain something to me? in C, i tend to write this:

int* x;

i write it like that because i believe i am bringing into existence x, whose type is "a pointer to an integer". it's not an int, it's an int pointer. so i write int*, because that's what type it is. it seems clearer that way. however i often see this:

int *x;

this seems less clear, but some (most?) people obviously think THAT way is the clearer way. if you do, what's your thought process?

i suppose if you write int *x = 9; then it makes sense as you need to dereference it to set it, right? so you're probably thinking of the * as an operator and not as a type specifier/modifier. e.g. i'm thinking of it as an adjective, and you're thinking of it as a verb? something like that?

my hottest take here is probably this:

int_ptr a;
printf("%x\n", a); // 0x0
printf("%d\n", sizeof(int_ptr)); // 8

a = stalloc(sizeof(int_ptr));
printf("%x\n", a); // 0x02BF26A...

poke(a, 10);
printf("%d\n", peek(a) ); // 10

@jk Consider this:

int* a, b;

This declares one pointer and one integer, which doesn't agree with the way you were thinking of it in your first example.

@kaelef i never really notice this i guess since i never do multiple declarations on the same line, they've always looked ugly to me

@jk Like you said, it's a matter of preference in a simple declaration like you showed, but it might lead one to thinking of '*' in a way different from how the language technically views it, so I'd discourage a beginner from using that form. It's strictly an operator that binds to the declarator, not the type specifier.

One of the great things about C is that it gives you a ton a freedom as long as you know what you're doing!

@jk there’s the declaring multiple case, for example, i sometimes have to do it.e. struct addrinfo ai, *next_ai; (for things like say a linked list) - so i can define my struct and a pointer for iterating through it
@cb y'know i pretty much never do multiple definitions on a line! for some reason i find it harder to read, which is funny, since i learnt pascal before C, and i (and everyone i saw) did it all the time there, since pre-declaring all your variables at the beginning of a function was kind of the pascal style
@jk predeclaring was also required pre C99 (but very goofy with K&R) so you’ll see it as old habit in a lot of places

@jk
I write C like this thinking int = *x, i.e., x when dereferenced gives an int.

*x is an int, rather than x is an int pointer.

The two ways of thinking get mixed up with each other though… casting is (int *) x, usage is *x

@jk
The former makes more sense in a vacuum, but the latter is much less surprising since the “pointer-ness” is tied to the variable name rather than the type.

So

int* x, y;

gives you an int* x and a plain int y, not two pointers. Wheras

int *x, *y;

indicates that the pointer is tied to each name rather than the type.

(Not that it'd be particularly good practice to declare a pointer and a non-pointer in the same statement, but it still helps avoid mistakes)

@nytpu maybe this is why i never do multiple definitions on a single line! it's always looked confusing or ugly to me, style-wise
@jk I'd say the similarity to the deref operator. int *i is an i that can get assigned an &int, and which can yield an int when named *i.
@jk If you define multiple pointers at once, you have to write int *a, *b, *c; instead of int* a, b, c; or else b and c are not pointers at all.

@jk it's commonly taught that way for the reasons other folks have explained (it's how I was taught for sure). though I have seen a third option where the asterisk has whitespace on both sides like int * a; lol

if you're curious, the entire clusterfuck that is declaration syntax can be seen here: https://en.cppreference.com/w/c/language/declarations

Declarations - cppreference.com

@Skirmisher i dont understand why they dont just use my peek and poke syntax
@jk I think that the "int* x, y" example, even if you don't write like that (and I rarely do either), show that "the language doesn't think like that", and that's all the reason I need to avoid it. I don't want to fight the language when trying to internalise it, so I will as much as possible try to make my usage and mental model match how the language works, or else it will probably come back to bite me in some much more subtle case.
@jk Like, some languages DO think like "int* x", and in THOSE it makes sense to do that, but C is not one of them and trying to force it to be will not lead to anything good.
@jk Subtle cases like function pointers and array pointers, I guess.

@jk I thought it was extremely confusing. The object type is a pointer to an integer, not an integer, so wouldn't it be attached to the type specifier?

Honestly hate "int *p"

@shram86 @jk it’s really unfortunate that C semantics are the way they are, because you’d think int* x, y; declares two variables of type int*, but instead * is treated like some pseudofact about x and y is just a plain int.

@senj @shram86 @jk Right, "int *x" is how the language _actually works_. It may not be how we wished it worked, but that is how it works, so it is clearer to write things that way.

If you designed C now, you might design it so that "int* x" is how it works. But that would be a slightly different language.

@WAHa_06x36 @senj @jk does this mean that when parsed, every C interpreter just transposes the asterisk?

Every compiler I've ever used doesn't care where it goes. I know K&R do it one way, but practice is different....

@shram86 @senj @jk I don't mean the literal position of the asterisk, I mean what it looks like it means. Does the asterisk belong to the type, or to the name of the variable. You can place it anywhere, but semantically, only one way matches the way the C language works, and that is "int *x", the asterisk belongs to the variable name, not to the type.

@WAHa_06x36 @senj @jk I'm still unsure of what you mean by "the asterisk belongs to the variable name".

By that logic you can have a int *x and an int x and C wouldn't care but I'm pretty sure it does?

@shram86 @senj @jk Well the classic example is still "int* x, y", which gives you one pointer to int and one int, not two pointers. There it's pretty easy to see that the * belongs to x, not to int.
@shram86 @senj @jk Also, for more complicated cases there is no equivalent of writing "int*". For instance, "int (*func)(int x)" gives you a pointer to a function taking an int and returning an int. You can't write "int(*)(int) func", which would be the equivalent of the "int* x".

@jk I disagree with the C take on this, but the idea is that the value itself resides at the actual destination pointer address, rather than being the actual stack or heap variable's value stored in the variable. So the variable is "pointer-to-x", with the type of x being int.

But imo, they're wrong, and I always write it assuming the value stored *right here in the variable* is the type I care about, and that's `int* x`

@jk I think we're glossing over the important question here, which is: were these two groups happy for each other to go on using their own preferred version of "to each their own" or were they insisting everyone switch to the "correct" one?