Initializing global variables - where?

I realized that I am confused about initializing global variables. What I mean is this:

byte foo = 1;

void setup() {
}
void loop() {
}

This works, but is it kosher to do? I have been writing programs like this for a while without apparent problems. But it doesn't work for a structure or class:

struct fooType {
  byte bar;
};

fooType foo;

foo.bar = 1;

void setup(){
}

void loop(){
}

Yields the error: expected constructor, destructor, or type conversion before '.' token. It only works if the line foo.bar = 1 is in setup().
But I don't understand why... and it's making me wonder if there's something wrong in general with assigning values to globals in that blank space before setup(). I suspect the answer has something to do with how the IDE rearranges the source file.

You can only initialize global variables to constant values outside of a function (address of a static or extern variables counts as constant in this case). The compiler puts the initialized values into the memory location where the global variable lives. I believe in the case of the Arduino, it puts it into a section in flash memory, and then it is copied to the actual location in sram as part of the initialization.

In C++ (but not C), if you declare something as const, that is treated by the compiler as a constant, so the following would work:

const int alpha = 100;
int beta = 200 + alpha;

Note, if you declare a variable using a class and pass arguments to that class, the compiler creates a function to do the initialization, and calls it before it gets to the setup function. This function is called a constructor.

Slightly expanded structure to illustrate initialization of instance of global structures -

struct fooType
{
    byte    bar;
    float   tab;
};

fooType foo = { 1, 12.05f };

In C++ (but not C), if you declare something as const, that is treated by the compiler as a constant,

I hope you're not suggesting that the "const" keyword is not part of C?

You can only initialize global variables to constant values outside of a function (address of a static or extern variables counts as constant in this case).

I don't see how this statement relates to what OP is trying to do.

The problem, OP, is that the initialization of variables, outside of a function, can only happen when the initialization and declaration occur in the same statement.

byte foo = 1;

is declaring and initializing a variable in one statement.

struct fooType {
  byte bar;
};

fooType foo;

foo.bar = 1;

The fooType foo; statement declares a variable. Then, with a separate statement you try to initialize it. That is what is not allowed. The way that lloyddean shows is how you would declare and initialize foo in one statement.

Otherwise, the initialization code has to go inside a function, like setup().

The problem, OP, is that the initialization of variables, outside of a function, can only happen when the initialization and declaration occur in the same statement.

Ahhh… too bad the compiler doesn’t yield that error message instead!

Looks like this syntax:

fooType foo = {.bar = 1};

is legal in some C implementations, but not in our version.

I could use a constructor, but my initial thought was that the code would be more readable using the field names rather than something like {1,0,false,"name"}.

I could use a constructor, but my initial thought was that the code would be more readable using the field names rather than something like {1,0,false,“name”}.

I agree it would. To use the names, you simply need to move the declarations into a function, like setup(). There is some overhead involved in separating the declaration and initialization. That may, or may not, be a problem for you.

AWOL:

In C++ (but not C), if you declare something as const, that is treated by the compiler as a constant,

I hope you're not suggesting that the "const" keyword is not part of C?

No, const is part of ISO C (it was added in the original ANSI C in 1989). However there are subtle differences between const in the C and C++ languages. One of the differences is in C++ a const declaration creates a constant that is usable in other places that need a constant value, such as initialization of global variables (*), but in C it creates a variable, and the variable while it cannot change, is not treated as a constant.

  • Just to confuse things more, you can't use a const int in a #ifdef type situation, since the phases of translation has the preprocessing done before the semantical processing is done.

It is a feature of the C 99 standard, called designated initializers. Unfortunately, it is not in the C++ standard, even the C++11 standard that just came out. Since Arduino uses C++, you can't use it in your code.