7 ms·
> (In fact, that's what array[i] means – the language defines it to be a synonym for *(array+i).) To really drive home the primitiveness of C arrays, should pr
by smcameron 5y ago
> (In fact, that's what array[i] means – the language defines it to be a synonym for *(array+i).)
To really drive home the primitiveness of C arrays, should probably also mention that, because addition is commutative, you could also write
i[array]
and somewhat surprisingly, it will compile, and work, and it means "*(i + array)" which is equivalent to "*(array + i)"
But nobody really does that, because that would be kind of insane.
- unwind 5y agoOnce the point is home, you can drive it a little bit more by exploiting the fact that string literals can be converted to pointers to the first characters, and do putc(2["ABCDEF"], stdout); This prints 'C'.
- deleted 5y ago[deleted]
- deleted 5y ago[deleted]
- danielozcpp 5y agoint const* const x; // C int const& x; // C++ A reference is functionally equivalent to a const pointer. (Reference reassignment is disallowed. Likewise, you cannot reassign a const pointer. A const pointer is meant to keep its pointee [address].) The difference between them is that C++ const references also allow non-lvalue arguments (temporaries). It is much easier to read from right to left when decoding types. Look for yourself: - double (* const convert_to_deg)(double const x) // const pointer to function taking a const double and returning double - int const (* ptr_to_arr)[42]; // pointer to array of 42 const ints - int const * arr_of_ptrs[42]; // array of 42 pointers to const ints - int fun_returning_array_of_ints()[42]; Try it out yourself: https://cdecl.org/ https://cdecl.org/ Hence, I am an "East conster". (Many people are "West consters" though.) You can return function pointers: typedef struct player_t player_t; // let it be opaque ;) int game_strategy1(player_t const * const p) { /* Eliminate player */ return 666; } int game_strategy2(player_t const * const p) { /* Follow player */ return 007; } int (* const game_strategy(int const strategy_to_use))(player_t const * const p) { if (strategy_to_use == 0) return &game_strategy1; return &game_strategy2; } Functional programming = immutable (const) values + pure functions (no side effects). Consting for me is also a form of documentation/specification. "East const" for life! :)
- harry8 5y ago10 or 42?
- danielozcpp 5y agoThank you. 42. I edited my comment above.
- bachmeier 5y ago> nobody really does that, because that would be kind of insane Yeah. That's why people don't do things in C. It's more like most C programmers probably weren't aware of this. After your comment, we'll start to see C codebases everywhere with that.
- colejohnson66 5y agoThis “trick” has been know at least as far back as 2008: https://stackoverflow.com/questions/381542/with-arrays-why-is-it-the-case-that-a5-5a https://stackoverflow.com/questions/381542/with-arrays-why-i...
- lifthrasiir 5y agoOne of the very first IOCCC winners used the trick in 1984 (1984/anonymous): int i;main(){for(;i["]<i;++i){--i;}"];read('-'-'-',i+++"hell\ o, world!\n",'/'/'/'));}read(j,i,p){write(j/p+p,i---j,i/i);}
- jakeva 5y agowhat does this program do? i compiled it and ran it and got no output. i hope i haven't fork bombed myself or something
- lifthrasiir 5y agoPrints "hello, world!", assuming sizeof(int) == sizeof(char*) (and the same alignments and ABI, etc).
- jfrunyon 5y agoI think this is equivalent to: int i; int main(){ for( ; i["]<i;++i){--i;}"]; // loop until i == 14? (the NUL byte on the end) read('-'-'-',i+++"hello, world!\n",'/'/'/') // read(0, <one byte of "hello, world!\n" at a time>, 1) ) {}; } int read(j,i,p){ write(j/p+p,i---j,i/i); // write(0/1+1, i-- - 0, 1) --> write(1, i, 1) --> write a byte to STDOUT }
- travelbuffoon 5y agoSpeaking of such funny business: unfortunately I have seen *(array + i) quite a few times. To make it worse, it’s in a parser for external data in binary format, where you really shouldn’t be playing funny tricks.
- lifthrasiir 5y agoIf array were, say, uint32_t* then what `*(array + i)` would do is actually `(intptr_t)array + i * 4` and not `(intptr_t)array + i`. If array were uint16_t* then it's `(intptr_t)array + i * 2`. In short the way the pointer arithmetic gets translated greatly depends on the type of the pointee and thus is not as primitive as it can be.
- kzrdude 5y agoI think it depends on the coder if it makes more sense to them to write out the scale by element size or not. For me, the `+` is just pointer arithmetic and of course an addition in number of elements (so I don't think of the scaling at all). Just saying that "actually it's just array + i" makes more sense - for me(!).
- lebuffon 5y agoInteresting. Looks like Forth. :-)
- a3n 5y agoThis sub-thread is better than a Vim thread. :)
- Zababa 5y agoThis is actually a really good way to drive home that arrays don't really "exists" in C and are just syntaxic sugar for pointer arithmetic.
- omegalulw 5y ago"Because real programmers only need void*".
- Zababa 5y agoThere's a language for that https://github.com/kyouko-taiga/void-lang https://github.com/kyouko-taiga/void-lang
- kevin_thibedeau 5y agoThey exist in the sense that their length is sometimes known if the full definition is visible. sizeof(array) isn't the same as sizeof(generic ptr to array).
- sn41 5y agoThis is not entirely a complete view. For example, sizeof() operator returns the declared size of an array. It seems that C recognizes the concept of an array.
- brundolf 5y agoThe OP probably doesn't want people to run away and never look back