1

I was disappointed to learn recently that C does not allow assignment of variables during static variable initialization, unlike C++. E.g. the following code compiles as C++...

#include <stdio.h>

int foo()
{
  return 1;
}

static int g_i = foo();

int main( int argc, char* argv[] )
{
  printf( "%d\n", g_i );
  return 0;
}

...but issues the following error with a C compiler:

>cc -g main.c
main.c:8:1: error: initializer element is not constant
 static int g_i = foo();
 ^

I thought I could be clever by using the comma operator a-la:

static int g_i = ( foo(), 1 );

...but the compiler seemed unimpressed with my attempted cleverness, and output effectively the same error:

>cc -c main.c
main.c:8:1: error: initializer element is not constant
 static int g_i = ( foo(), 1 );
 ^ 

:(

Q: Why does use of the comma operator not work? I may be unaware of some subtlety, but my understanding led me to think it should have worked: the C compiler is demanding g_i be initialzed to a compiletime constant; supposedly the comma operator would have offered me evaluation of the code left of the comma, but assignment of the code right of the comma, which is a compiletime constant.

Q: Are there any hacks - I don't care how dirty - that would allow assignment to g_i the return value of foo() to g_i?

This is a simplified representation of a C program where I really just want to call a function before main() - I don't care about the return value, but it's a more complicated problem to call a void function before main(), which I would rather sidestep altogether by using an int function whose value is assigned to a throwaway static int variable.

11
  • 2
    Why do you want to sidestep calling a void function before main? Even though standard C has no way of doing that, most platforms and compilers actually do. Commented Jun 15, 2017 at 1:53
  • 1
    Not sure if you would call this a "dirty hack", but write static int g_i;, and then in the first line of main(), put g_i = foo(); Commented Jun 15, 2017 at 2:23
  • 1
    If code was static int g_ai = foo(); in a.c and static int g_bi = foo(); in b.c, would you care which one is called first? Commented Jun 15, 2017 at 3:22
  • @Siguza - if you have experience in that regard, could you post an answer at stackoverflow.com/questions/43150645/… ? I found an answer to that question, which I posted, but it was quite complex in my opinion. If you know of something easier, I'd be eager to learn. Commented Jun 15, 2017 at 17:11
  • 1
    @chux Just inelegant, in my opinion, but by no means the end of the world. What you point out is true and on-point. In my case, though, if the init() function were to have failed, the system is likely hosed anyway (e.g. what to do if pthread_mutex_init() fails?). So I was relying on the "unlikelihood" of init() failing. This question was somewhere between real-world application and academic curiosity, because of my initially being caught off-guard by C demanding compiletime constants for static initialization. Commented Jun 15, 2017 at 19:32

1 Answer 1

8

C does not support dynamic initialization. For this reason, static objects are required to be initialized with constant expressions. Constant expressions are not allowed to involve any run-time computations, even if these computations do not affect the final value of the expression. Your expression with comma operator is not a constant expression.

(Moreover, comma operator is prohibited in C constant expressions even if you don't call any functions from them. E.g. even something as trivial as (1, 2, 3) is not a constant expression either.)

All static objects in C have to be initialized at compile time, at least conceptually. The word "conceptually" in this case refers to the fact that, say, address constant expressions may actually be evaluated much later, even at load time. But the point is that once your program starts running any user-level code, all static objects have to have already known pre-evaluated values, as if they were initialized at compile time. For this reason C (as opposed to C++) does not have/does not need the concept of initialization order for static objects and cannot possibly suffer from SIOF.

So, there's no way around this restriction in standard C. You will not be able to initialize a static object with something that requires (or in any way involves) running code at run-time. Your implementation might provide implementation-specific features that might be able to do something like that, but this is way outside the realm of C language itself.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.