Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fidergo-stephane-gourichon/792c194e1b051a70995c27b5af8df92d to your computer and use it in GitHub Desktop.
Save fidergo-stephane-gourichon/792c194e1b051a70995c27b5af8df92d to your computer and use it in GitHub Desktop.
In C, compile time constant structs and array with deep self-reference.
/* Summary: In C, compile time constant structs and array with deep self-references.
** Context: const and compile-time constants
Constructs fully determined at compile time have some benefits.
But const in C is weaker than constexpr that C++ has.
As prog-fh summarizes on
https://stackoverflow.com/questions/66144082/why-does-gcc-clang-handle-code-slightly-differently-example-given
> "The const means « I swear that I won't change the value of this variable » (or the compiler will remind me!). But it does not
> mean that it could not change by another mean I don't see in this compilation unit; thus this is not exactly a constant."
One example of invalid C:
const int mysize = 2;
const int myarray[mysize];
gcc: error: variably modified ‘myarray’ at file scope
clang: warning: variable length array folded to constant array as an extension [-Wgnu-folding-constant]
const int myarray[mysize];
** Good news: C can do compile time constant structs and array with deep self-references.
Yes, in C you can define and fully declare complex data structures that are accepted as compile-time constants, *including
pointers to parts of itself*.
See "self-contained, statically allocated, totally const data structure with backward and forward references (pointers)?" for a
previous example at
https://stackoverflow.com/questions/47037701/can-c-syntax-define-a-self-contained-statically-allocated-totally-const-data-s
The code below compiles without warning.
gcc -S -W -Wall -Wextra self_referencing_construct_with_deep_self_references.c
*/
#include <stdio.h> // for NULL
/* Example too trivial to be actually useful. */
const int mysize = 2;
const int myarray[mysize];
struct selfref
{
const struct selfref *const pointer;
};
const struct selfref permutation[2] = { {&permutation[1]}, {&permutation[0]} };
void permutation_check(void)
{
printf("Adresses:\n%p\n%p\n", &(permutation[0]), &(permutation[1]));
printf("Pointed addresses:\n%p\n%p\n", permutation[0].pointer, permutation[1].pointer);
}
/* Example hinting at the existence of real-life uses. */
struct question_answers
{
const char *const question;
const char *const answer1;
const struct question_answers *const next1;
const char *const answer2;
const struct question_answers *const next2;
};
const struct question_answers dialog_as_array[] = {
{ "Which pill?",
"Red pill", &dialog_as_array[2],
"Blue pill", &dialog_as_array[1] },
{ "You wake up in your bed. The story ends. ",
"Believe it was all a dream.", NULL,
"Realize matrix has won.", NULL },
{ "Welcome to the Real World. What next?",
"Become Neo.", &dialog_as_array[4],
"Give up.", &dialog_as_array[3] },
{ "Mister Anderson!",
"Billions of people living out their lives, oblivious.", NULL,
"Evolution, like the dinosaur.", NULL },
{ "Where we go from there is a choice I leave to you.",
"Go crazy.", NULL, "This is fine.", NULL },
};
struct dialog
{
const struct question_answers entry;
const struct question_answers blue_pill_taken;
const struct question_answers red_pill_taken;
const struct question_answers red_pill_taken_give_up;
const struct question_answers red_pill_taken_become_neo;
};
const struct dialog dialog_as_struct = {
.entry = { "Which pill?",
"Red pill", &dialog_as_struct.red_pill_taken,
"Blue pill", &dialog_as_struct.blue_pill_taken },
.blue_pill_taken = { "You wake up in your bed. The story ends. ",
"Believe it was all a dream.", NULL,
"Matrix has won.", NULL },
.red_pill_taken = { "Welcome Neo to the Real World. What next?",
"Become Neo.", &dialog_as_struct.red_pill_taken_become_neo,
"Give up.", &dialog_as_struct.red_pill_taken_give_up },
.red_pill_taken_give_up = { "Mister Anderson!",
"Billions of people living out their lives, oblivious.", NULL,
"Evolution, like the dinosaur.", NULL },
.red_pill_taken_become_neo = { "Where we go from there is a choice I leave to you.",
"Go crazy.", NULL, "This is fine.", NULL },
};
int main(void)
{
permutation_check();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment