> a[b] is literally equivalent to *(a + b). You can thus write some absolute madness such as 41[yourarray + 1]. Wow. This has to be the best C obscurity that I've ever seen.
Some Obscure C Features
31–40 of 147 posts
Re: Some Obscure C Features
#32The preprocessor trick of passing function macros as parameters is not that obscure. I have seen it used and I've used it myself. It is very useful when you have a list of static "things" that you need to operate on. Say I have a static list of names and I would like to declare some struct type for each name. I also would like to create variables of these structs at some point, and I would always do so for the entire…
Re: Some Obscure C Features
#33Compile-time trees are possible without compound literals.
More than twenty years ago, I made a hyper-linked help screen system a GUI app whose content was all statically declared C structures with pointers to each other.
At file scope, you can make circular structures, thanks to tentative definitions, which can forward-declare the existence of a name, whose initializer can be given later.
Here is a compile-time circular list
struct foo { struct foo *prev, *next; };
struct foo n1, n2; /* C90 "tentative definition" */
struct foo circ_head = { &n2, &n1 };
struct foo n1 = { &circ_head, &n2 };
struct foo n2 = { &n2, &circ_head };
You can't do this purely declaratively in a block scope, because the tentative definition mechanism is lacking.About macros used for include headers, those can be evil. A few years ago I had this:
#include ALLOCA_H /* config system decides header name */
Broke on Musl. Why? ALLOCA_H expanded to . But unlike a hard-coded #include , this is just a token sequence that is itself scanned for more macro replacements: it consists of the tokens {}. The on Musl defines an alloca macro (an object-like one, not function-like such as #define alloca __builtin_alloca), and that got replaced inside , resulting in a garbage header name.Re: Some Obscure C Features
#34Re: Some Obscure C Features
#35> a[b] is literally equivalent to *(a + b). You can thus write some absolute madness such as 41[yourarray + 1]. Wow. This has to be the best C obscurity that I've ever seen.
Re: Some Obscure C Features
#36sizeof actually doesn't evaluate its expression for side effects most of the time; only if the operand is a variable-length array is it evaluated.
The standard says:
"If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant."
But what does it mean to evaluate the operand?
If the operand is the name of an object:
int vla[n];
sizeof n;
what does it mean to evaluate `n`? Logically, evaluating it should access the values of its elements (since there's no array-to-pointer conversion in this context), but that's obviously not what was intended.And what about this:
sizeof (int[n])
What does it mean to "evaluate" a type name?It's not much of a problem in practice, but it's difficult to come up with a consistent interpretation of the wording in the standard.
Re: Some Obscure C Features
#37A nice but I guess more of a linker feature is if you declare a function as __weak__, you can check it at runtime for == NULL to determine if the application was built with the function defined.
Re: Some Obscure C Features
#38Most of these are due to the cruft added in C99 and later. Compile-time trees are possible without compound literals. More than twenty years ago, I made a hyper-linked help screen system a GUI app whose content was all statically declared C structures with pointers to each other. At file scope, you can make circular structures, thanks to tentative definitions, which can forward-declare the existence of a name, whose…
Re: Some Obscure C Features
#39The preprocessor trick of passing function macros as parameters is not that obscure. I have seen it used and I've used it myself. It is very useful when you have a list of static "things" that you need to operate on. Say I have a static list of names and I would like to declare some struct type for each name. I also would like to create variables of these structs at some point, and I would always do so for the entire…
I used this trick to declare and generate code for an entire parser, it's lovely.
I recently switched to the other style of C-macro though:
#define X(A, B, C) ...
#include
#undef X
This style is less powerful but doesn't require the annoying \ at the end of lines.Re: Some Obscure C Features
#40 int b[const 42][24][*]
but you can get more fun with variably modified array parameters instead of just constants like 42. For example, double sum_a_weird_shaped_matrix(int n, double array[n][3*n]) {
double total = 0;
for (int x = 0; x
has a variable and a more complicated expression in those positions.But those variably modified parameters can have arbitrary expressions in them, like
int last(size_t len, int array[restrict static (printf("getting the last element of an array of %zu ints\n", len), len--)]) {
return array[len];
}
C++ denies us this particular joy which could have made function overload resolution even more fun.