6 ms·
Thanks for submitting this. I'm teaching myself C so these high level overviews are super useful for improving my intuition. In the following example, shouldn'
by nadavision 4y ago
Thanks for submitting this. I'm teaching myself C so these high level overviews are super useful for improving my intuition.
In the following example, shouldn't there be an asterisk * before the data argument in the getData function call? The way I understand it the function is expecting a pointer so you would need to pass it a pointer of the data object.
>
"If you want to “return” memory from a function, you don’t have to use malloc/allocated storage; you can pass a pointer to a local data:
void getData(int *data) {
data[0] = 1;
data[1] = 4;
data[2] = 9;
}
void main() {
int data[3];
getData(data);
printf("%d\n", data[1]);
} "
- torstenvl 4y agoNo, it's correct. The asterisk is a little inconsistent, in that it means two opposite things. In the declaration it means "this is a pointer." However, in an expression, it means "this is the underlying type" and serves to dereference the pointer. int a = 5; int *x; // this is a pointer x = &a; int c = *x; // both c and *x are ints If it were *data, it would be equivalent to *(data + 0), which is equivalent to data[0], which is an int. You don't want to pass an int, you want to pass an *int.
- karatinversion 4y agoThe way I got this to stick in my head was to always think of * as dereferencing, and tell myself that int *x; is declaring that the type of *x is int.
- unsafecast 4y agoIt's not just a memorization trick; that's exactly what the statement means. If you do int *x, y; You're saying that both *x and y are integers.
- pilif 4y ago... which is why I never understood why this is the convention rather than int* x, y. Does somebody know?
- Twisol 4y agoI don't know for certain, but I suspect it simplified the language's grammar, since C's "declaration follows use" rule means you can basically repurpose the expression grammar for declarations instead of needing new rules for types. This is also why the function pointer syntax is so baroque (`int (*x)();` declares a variable `x` containing a pointer to a function taking no parameters and returning an int).
- proto_lambda 4y agoYou must've misunderstood, your statement looks like both x and y are `int *`, but in fact only x is an `int *`, while y is an `int`.
- unsafecast 4y agoBecause now you've got an int pointer and an int. The star associates with the right, not left. I prefer to use the variant you described though, because it feels more natural to associate the pointer with the type itself. As far as I know, the only pitfall is in the multiple declaration thing so I just don't use it. IMO, it's also more readable in this case: int *get_int(void); int* get_int(void); The second one more clearly shows that it returns a pointer-to-int.
- thomastjeffery 4y agoMultiple declaration is generally frowned upon, because you declare the variables without immediately setting them to something. If you always set new variables in the same statement you declare them, then you don't use multiple declarations, which means there is no ambiguity putting the * by the type name. So convention wins out for convention's sake. And that's the entire point of convention in the first place: to sidestep the ugly warts of a decades-old language design.
- ben_bradley 4y ago
- torstenvl 4y agoI like that a lot! However, it makes things like int *x = &a; a bit more confusing/inconsistent.
- pif 4y agoNot at all! a is int; &a is pointer to int; x is pointer to int; *x in again int.
- fwip 4y agoGotcha, so it's kind of like: int (*(x = &(a))); i i p p i // i means int, p means pointer
- thomastjeffery 4y agoI prefer to think of it as (int *) x = &(a); i p p a i // a means address Which is why I prefer to write int* x = &a; "integer pointer" named "x" set to address of integer "a". --- As a sibling comment pointed out, this is ambiguous when using multiple declaration: int* foo, bar; The above statement declares an "integer pointer" foo and an "integer" bar. It can be unambiguously rewritten as: int bar, *foo; But multiple declaration sucks anyway! It's widely accepted good practice to set (instantiate) your variables in the same statement that you declare them. Otherwise your program might start reading whatever data was lying around on the stack (the current value of bar) or worse: whatever random memory address it refers to (the current value of foo).
- fwip 4y agoThanks :)
- HKH2 4y agoThanks. Now I understand why I found pointers difficult. It's the declaration that confused me.
- layer8 4y agoYou can read a declaration like `int x` as “`x` is an int”, and hence x is an int pointer.
- lioeters 4y agoWith the asterisks backslash escaped: > ..read a declaration like `int *x` as "`*x` is an int"..
- kccqzy 4y agoI think it would help if beginners learn a language other than C to learn about pointers. My first language was Pascal, and it didn't have a confusing declaration syntax, nor did it have a confusing array decay behavior so it was much much easier to learn. Nowadays of course I don't think about it but those details mattered to beginners.
- HKH2 4y agoYeah. Since trying C, I've learnt a bit of Rust, so referencing and dereferencing seem straightforward without abstracting references using a pointer.
- seritools 4y agothe local variable data effectively decays to int*. *data would give you an int, &data would give you an int*.
- unwind 4y agoNo, it's fine. The name of an array decays to a pointer to the first element in various contexts. You could do `&data[0]` but it means exactly the same thing and would read as over-complicated things to C programmers.
- nadavision 4y agoThanks for all the great answers. The inconsistency between pointer deceleration and dereference syntax was what got me. :)