How can I perform pre-main initialization in C/C++ with avr-gcc?

You can make the above very slightly shorter by giving "initialize" a return type, and using that to initialize a global variable:

int initialize();
int dummy = initialize();

However, you need to be careful with this, the standard does not guarantee that the above initialization (or the one for your init object) takes place before main is run (3.6.2/3):

It is implementation-defined whether or not the dynamic initialization (8.5, 9.4, 12.1, 12.6.1) of an object of namespace scope is done before the first statement of main.

The only thing that is guaranteed is that the initialization will take place before 'dummy' is ever used.

A more intrusive option (if it's possible) might be to use "-D main=avr_main" in your makefile. You could then add your own main as follows:

// Add a declaration for the main declared by the avr compiler.
int avr_main (int argc, const char * argv[]);  // Needs to match exactly

#undef main
int main (int argc, const char * argv[])
{
  initialize ();
  return avr_main (argc, argv);
}

At least here you're guaranteed that the initialization will take place when you expect.


Your solution in simple and clean. What you can additionally do is to put your code in anonymous namespace. I don't see any need to make it better than that :)


You can use GCC's constructor attribute to ensure that it gets called before main():

void Init(void) __attribute__((constructor));
void Init(void) { /* code */ }  // This will always run before main()

Here's a somewhat evil method of achieving this:

#include <stdio.h>

static int bar = 0;

int __real_main(int argc, char **argv);

int __wrap_main(int argc, char **argv)
{
    bar = 1;
    return __real_main(argc, argv);
}

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

Add the following to the linker flags: --wrap main

eg.

gcc -Xlinker --wrap -Xlinker main a.c

The linker will replace all calls to main with calls to __wrap_main, see the ld man page on --wrap