My favorite C "quirk": If you have an array and you want to access an item of it, you can swap the variable and the index number (put the variable name inside brackets and the number outside): a[5] is the same as: 5[a] why? a[5] is actually sugar for *(a + 5), so by commutative property, you can also do *(5 + a) to access the same memory position :-)
That's #15 on the list.
Mildly interesting quirks of C
21–30 of 91 posts
Re: Mildly interesting quirks of C
#22Here are two of my favorite obscure quirks of C: struct X { char x[8]; }; struct X awoo(void); printf("%s\n", awoo().x); The above is UB in = C11. [0] struct X { char b[8]; } foo(); int *b = foo().b; printf("%s\n", b); The above is UB in >= C11 and valid in [0] https://wiki.sei.cmu.edu/confluence/plugins/servlet/mobile?c... [1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1285.htm
I really wish both would be valid in C11. Or rather I wish I had "systems-C" where all the undefined behaviour added for high performance computing was filed off and defined as "whatever the platform does".
UBs were added for cross-incompatibilities, where operations were too "core" (and / or untestable) for IBs to be acceptable. The reason was not performance (aside from not imposing a runtime check where that would have been possible) but portability:
> 3.4.3 undefined behavior behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements
Those UBs were leveraged later on by optimising compilers, because they provide constraints compensating for C's useless type system.
So you can just use a non-optimising compiler or one which only does simple optimisations (e.g. tcc), and see what the compiler generates from your UBs.
Re: Mildly interesting quirks of C
#23Re: Mildly interesting quirks of C
#24Whenever the subject of C/C++ quirks is brought up, I always like to point out the Deep C/C++ presentation: http://www.pvv.org/~oma/DeepC_slides_oct2011.pdf Source: https://freecomputerbooks.com/Deep-C-and-Cpp.html#downloadLi... Previous discussion: https://news.ycombinator.com/item?id=3093323 It could be considered a bit dated at this point (It's before C++11) but I find it still both entertaining and educating.
Re: Mildly interesting quirks of C
#25As someone who's moved on to Rust, I see this as one long list of nightmares.
C and Rust don't perfectly overlap, especially since Rust is more a replacement to C++ than C.
Re: Mildly interesting quirks of C
#26My favorite C "quirk": If you have an array and you want to access an item of it, you can swap the variable and the index number (put the variable name inside brackets and the number outside): a[5] is the same as: 5[a] why? a[5] is actually sugar for *(a + 5), so by commutative property, you can also do *(5 + a) to access the same memory position :-)
Re: Mildly interesting quirks of C
#27My favorite C "quirk": If you have an array and you want to access an item of it, you can swap the variable and the index number (put the variable name inside brackets and the number outside): a[5] is the same as: 5[a] why? a[5] is actually sugar for *(a + 5), so by commutative property, you can also do *(5 + a) to access the same memory position :-)
One funny variant is this expression: "abcde"[4]
Re: Mildly interesting quirks of C
#28Re: Mildly interesting quirks of C
#29Re: Mildly interesting quirks of C
#30#2 and #5 can be combined to make and interesting hack. When combinded with memcpy you can do
int *a = memcpy(&(int){0}, b, sizeof *b);
C23 typeof makes this even more interestingIf you what an challenge here is a standard compliant c code. Try to undestand it. If can understand you are a master of c's type system
static int* (*const *(*restrict x)[5])(volatile union {struct{int a;int b;};}[static const restrict 5], register enum{HELLO,WORLD} a) = {0};