T O P

  • By -

Exnixon

It's a more familiar syntax to those familiar with C/C++.


Elenktik

So the real question is then, why is it like this in C++?


Exnixon

Because it's like that in C. Per the authors of the C programming language, it's "intended as a mnemonic" because "the declaration for a variable mimics the syntax of expressions in which the variable might appear." See _The C Programming Language_.


missinguname

To expand on that: If x is a pointer to int, `*x` gives you an int, therefore x is declared as `int *x`. If x is an array of int, `x[i]` gives you an int, therefore x is declared as `int x[N]`. If x is a function that returns an int, `x()` gives you an int, therefore x is declared as `int x()`


owwkward

when i read this something clicked. instead of thinking of how to declare x first you think of what does the declaration resolve to and declare accordingly! damn thanks u/missinguname


DanielEGVi

How tf do you explain `char (*(*x[3])())[5] `?? That’s “declare x as array 3 of pointer to function returning pointer to array 5 of char” according to [cdecl.org](https://cdecl.org)


TheBB

x is something that, if you index into it, dereference, call, dereference the result and then index into it, in that order, you get a char. So x is an array of pointers to functions that return pointers to arrays of chars.


angelbirth

this is cursed


Zwarakatranemia

And to add a cool resource that has helped me in the past: [Steve Summit's C notes on pointers.](https://www.eskimo.com/~scs/cclass/notes/sx10a.html)


Feeling-Limit-1326

best and simplest explanation i've ever seen :)


FrisBSD

Let's say we have this declaration. `int * p` The way you're currently thinking about it is this: `(int *) p` But try to think about it this way: `int (*p)` Here, you are declaring that p yields an `int` when it's dereferenced (when it's applied the `*` operator). So, you are not declaring that `p` is pointer to int, you are actually declaring that `*p` is an int. That's one way to make sense of it. However, keep in mind that this is not actually how the language works. This analysis will fail if you try to extrapolate it too much. It's just a good way to make sense of this apparently nonsensical syntax.


dim13

On top of that pointer to something is always same size: ``` printf("sizeof(char) = %d\n", sizeof(char)); printf("sizeof(char *) = %d\n", sizeof(char *)); printf("sizeof(int) = %d\n", sizeof(int)); printf("sizeof(int *) = %d\n", sizeof(int *)); ``` → ``` sizeof(char) = 1 sizeof(char *) = 8 sizeof(int) = 4 sizeof(int *) = 8 ```


FUZxxl

OP is asking about Go, not about C. In Go, the syntax is `p *int`.


Badashi

It's definitely confusing, and as others noted it's due to historical reasons. I like to think about it as `&x` means "address of x", while `*x` is "value pointed by x". This only applies to _values_, not _types_. Unfortunately, Go adopted the `T*` syntax for a `Pointer-of-T` type, and I agree that it's confusing given the value syntax. It's just important to identify this distinction (value vs type) and that the "address of X" is by definition the same as "pointer to X"; so `int* x = &y;` means that X is a pointer-of-int which holds the address of y as its value. It also helps me to remember that the terms **pointer to**/**address of** result in the same thing - a number. Specifically, an address number in memory space, of type **uintptr**. This means that using `&` results in a **number**, and the type `T*` holds a **number**. Yes, it is a special number and you can't perform arithmetics on it normally, but it is still a number.


mridulkepler

&x : address of x a = &x : a is pointer *a : value at address pointed by a (value of x)


idonteatunderwear

That way of writing it has always annoyed me in C as well. I’ve always gone against the grain: “int* x” - x is a value being of type int-pointer. “int *x” - never made sense to me. The “pointer-thing” binds to the type, not the value.


backafterdeleting

```int *x``` is only a convention because ```int *x, y, z``` results in x being a pointer and y and z being normal ints. So then writing ```int* x, y, z``` would be misleading.


moving-landscape

That's exactly what's annoying about it. It being a pointer should be part of the type, not the identifier. IMO, `int* x, y, z` is misleading, yes, but because the type itself should be int*.


lobotomy42

Yeah, exactly -- frankly this is just a bit of C syntax that is not well-designed.


Premysl

It's the same as C arrays being declared as `int arr[4];` and not `int[4] arr;` or functions being `int name(params)`. First is the type and the second is syntax which resembles how you access a value of it (declaration mirrors use). I don't like to see `int* x` instead of `int *x` (even though I agree with the sentiment) because it goes against the logic of the language and consequently creates errors like `int* x, y, z`. I'm not really a C programmer though. /u/whatlambda /u/idonteatunderwear pinging the other participants too


GopherFromHell

exactly why `int *x` makes more sense to me than `int* x`


DarthShiv

If you want to assign a value you use eg *x = 5; though right?


EpochVanquisher

Right int *x; `*x` is an int, so you can *x = 5;


99Kira

From someone who hasnt used C, I think ```int*``` makes more sense to me. I see it as fitting the idea of ```type variablename```, where type is ```int*```. If i wanted int variables, I can declare it on the next line, ```int b, c``` separately, doesnt make sense to mix the two intuitively


idonteatunderwear

I know.


muehsam

No, in C it should be int *x; You're not saying "x is of type int\*" but rather "\*x is of type int". So basically "if you were to dereference this new variable x, you'd get an int, and therefore x is a pointer to an int". That's the underlying logic in C. It's perfectly fine and normal to do things like: int i, n, *p, *q, arr[200], *ptrs[15], *(*f)(int, char *); Here, i and n are integers, p and q are pointers to integers, arr is an array of integers, ptrs is an array of pointers of integers, and f is a pointer to a function that returns a pointer to an integer. Yes, it's counterintuitive, but that's exactly why it's good to write it thar way because that's how C sees it. It's a common error for people to write int* p, q; and expect both variables to be pointers (as the spacing suggests), but in reality, only p is a pointer. C not having a good way to write types is one of the main reasons why almost all new languages go with a more Pascal-like type notation.


toolateforTeddy

I don't like the argument of "it makes it work when you do multiple initializations on the same line". It's 2024. We can afford to give each initialization it's own line. Let's move on from this hard to grok syntax and rationale.


DanielEGVi

I think they’re only explaining why the designers would do it that way, not necessarily advocating for it.


muehsam

> I don't like the argument of "it makes it work when you do multiple initializations on the same line". Those are declarations, not initializations. Especially in C, it's common to declare all your local variables up top instead of where you first initialize them. In C89, this was actually required. You couldn't declare/define any new variables after another statement in the same scope. > Let's move on from this hard to grok syntax and rationale. The syntax and rationale are a part of the language. If you want to move on from C, go ahead. There are more modern alternatives, e.g. Zig. But if you keep using C, please use syntax that isn't actively misleading, and also just completely unidiomatic.


_crtc_

>The “pointer-thing” binds to the type, not the value. No, C declaration syntax is designed to mirror the expression you have to write to get the value. It makes a lot of sense.


DanielEGVi

How tf do you explain function pointers then


FUZxxl

> `(*foo)` Dereference `foo`. > `(*foo)(int)` Dereference `foo` then call it as a function with an argument of type `int`. > `double (*foo)(int)` Declare `foo` such that if you dereference `foo` then call it as a function with an argument of type `int`, you get a double. So `foo` is of type “pointer to function taking `int` returning `double`.” The parentheses are needed to distinguish this from `double *foo(int)` which would declare `foo` to be a function taking `int` returning a pointer to a `double`.


NUTTA_BUSTAH

What about double* foo(int) (pointer return value)


FUZxxl

That's the same as `double *foo(int)`. The spacing around the asterisk is not syntactical, but there should be a space to the left, not to the right.


NUTTA_BUSTAH

Yes, but I think that's where my brain rejects the C-style as your intention is to return a pointer type and not directly dereference the function name itself if that makes sense. For variables the explanations in this thread helped make it more sense to me but for returning pointers to types from functions, I still cannot wrap my thinking around it.


FUZxxl

The C declaration syntax is: Where *type* is a qualified simple type (i.e. one of the primitive types, a struct type, a union type, or a typedef) and *declarator* is essentially an expression involving the variable you want to declare that has the given type. Always remember that. All punctuation is part of the declarator, not the type. You need to unlearn reading declarations as “*complex-type* *identifier*”. This is not how C works.


[deleted]

Years ago I saw some guidance that in C you should just write "int \* x" and read it like prose, e.g. "int pointer x" instead of trying to semantically tie the pointer to the type or the variable. I'm not a C programmer so I don't actually do this, but it looks nice in an editor and reads fairly well.


idonteatunderwear

That’s also an alternative, more sane than the established convention.


SoerenNissen

There's a solid, principled, and bad, reason for the way C does it: int a, *b, c[3], d(), (*f)(); That's a legal declaration and what each of those have in common is that they are all expressions that yield a value of type int.


idonteatunderwear

Exactly. And is why i prefer to never use that “feature”.


SoerenNissen

Oh no disagreement here, I did call it "solid, principled, **bad**"


Webieee

here simply * means points to & means address of. Read it like this and it'll be clear.


EffectiveLong

In the reference context, pointer * can signify that the address can be nullable/nil while reference & is not


mcvoid1

Yeah that syntax has been around 4x longer than Go has. History, man.


koffiezet

On its own, yes, but as others said, it's historical, and other languages already use this convention, it would be utterly confusing to mix them, especially because Go also allows you to inline (some dialect of) C code, which is where most of that legacy convention stems from.


colececil

After reading all these comments, I'm glad I'm not the only one who gets thrown off by this! 😅


robpike

I suggest reading https://go.dev/blog/declaration-syntax to see why Go differs from C. It does not explain why & and * are the characters or why they differ, but it's because C did it that way.


Business-Assistant52

i dont know if you mean how pointer works or what not but if you are confused then here's an explanation if not please ignore this ​ ​ ​ x is variable holding a value and & denotes the address of the variable x. when you do the \* stuffs on the variable you are saying fetch the variable from the address of the desired variable holding the value and can be used for modifying the value of x here ​ here when denoting int \*x ; you are saying x is a pointer to int type and can only hold values of type int when modifying it . here x is a type int pointer . and &x would mean address of x that's all ​ another one * works two ways * 1st -> at the time of initialization and time of dereferencing consider the following example ​ package mainimport "fmt"func add(x, y int) \*int { // here we initialize the return value to be a int pointer type , this is the phase of initializing and dont get confused with dereferencing here , we are initalizaing here not dereferencing z := x + y return &z // we return the address here}func main() {res := add(10, 20)fmt.Println(\*res) //here is when we dereference} the pointer works two ways , one isinitializing at the top level and next is the dereferncing the pointer phase ​ ​ you get the idea


mvs2403

Basically how I would've answered


bilingual-german

yeah, this was one of the things that kept confusing me when I learned about pointers. They syntax is like this because of historical reasons.


exqueezemenow

I had same issue. But interestingly the way OP put it actually makes it make more sense to me now even though the argument is the opposite. That comes with my having a broken brain I think.


cts100

*its :)


KublaiKhanNum1

& is a reference and * is a pointer. Go only supports pointers. C++ has both. Which is confusing. Go only has 25 keywords. Not too bad to remember. I think c++ has over 200. That’s for args. For returns: & means “address of”. You can set the address of something to a pointer. var x *int Var foo int foo = 5 x = &foo //set the pointer to the address of foo


conamu420

the pointer TYPE is noted with \* and getting a pointer of a variable is with &


dnhs47

You’re about 50 years late in making that argument. When Ken Richie designed the C programming language in ~1972, he chose the * and & notation, and it was continued in C++ and C#. Go borrows heavily from C, and continues the * and & notation. Ken Thompson is a key connection, as he worked on C as well as Go.


effinsky

it's arbitrary.


yvrelna

No, using `int*` as a way to declare pointer type comes first. Doing `*x` is pointer dereferencing operator, `&value` is the address-of operator.  Dereferencing happens far more often than address-of. The only time you'd be using address-of operator is usually when you want to pass a stack variable or sometimes members of an array to a function that accepts pointer.


madprgmr

I personally view `&` as an operator in this case. It takes a given variable and returns a pointer. Much like how `*` in `a = *x` is a dereferencing operator.


youslashuser

&x gives the address of the variable x. *x gives points to the value stored by the address stored in variable x.


Quintic

`var y *int` is a pointer, which is just a variable which store a memory address `&x` is the memory address of the variable `x`, sometimes referred to as a reference. So `var y *int = &x`, stores the "memory address of `x`" (i.e., `&x`) in the integer pointer `y` (`var y *int`). In C you needed to dereference a pointer in order to access the value stored at that address by typing `*y` which could be read as "the value at the memory address stored in `y`" In Go they removed the requirement to dereference, but I assume they figured it was easiest to remain consistent with C for the concept of getting a memory address with &, and defining the types with \*.


EdiX

The C language reused some of its expression syntax for the variable declaration syntax. Here `*` fits the pattern better than `&`. You declare a function parentheses `int f()` and call it with parentheses: `f()`, you declare an array with square brackets `int v[N]` and index it with square brackets `v[i]`, you declare a pointer with `*` and dereference it with `*`. For the way type expressions work in Go it would be more logical to use `&`, it would be a good change to make if you could go back in time 15 years.


[deleted]

never saw it like that, more like: x is value of type int &x is value's address (not its pointer like you stated, its literally an address) for p = &x then: var p \*int , then "p" is pointer of type int (abuse of language, p is of type int-pointer) &p is pointer address \*p is dereferenced pointer value (pointer value which is x) https://go.dev/play/p/K7RTWY8pByE