I'm trying to declare a static array of structures and can do so when it is declared globally, but not when declared static within a function.
Here's some sample code that works properly:
#include <stdio.h>
enum
{
Mammals,
Amphibians,
Avians,
Fish,
Human, Elephant, Horse,
Frog, Salamander,
Eagle, Sparrow, Duck,
Salmon, Carp, Tuna
};
typedef struct
{
int category;
int* examples;
int num_examples;
} classification_t;
static classification_t classifications[] = {
{ Mammals, (int[]){Human, Elephant, Horse}, 3 },
{ Amphibians, (int[]){Frog, Salamander}, 2 },
{ Avians, (int[]){Eagle, Sparrow, Duck}, 3 },
{ Fish, (int[]){Salmon, Carp, Tuna}, 3 }
};
int main(void)
{
for(int i=0; i<4; ++i)
{
printf("Category %d has %d examples\n", classifications[i].category, classifications[i].num_examples);
}
return 0;
}
Output:
Category 0 has 3 examples
Category 1 has 2 examples
Category 2 has 3 examples
Category 3 has 3 examples
This works because the big table of classifications is a static-global variable.
However, when I try to move the table within main (or any other function), I get an error:
prog.c:25:17: error: initializer element is not constant { Mammals, (int[]){Human, Elephant, Horse}, 3 },
In this code:
#include <stdio.h>
enum
{
Mammals,
Amphibians,
Avians,
Fish,
Human, Elephant, Horse,
Frog, Salamander,
Eagle, Sparrow, Duck,
Salmon, Carp, Tuna
};
typedef struct
{
int category;
int* examples;
int num_examples;
} classification_t;
int main(void)
{
//
// The ONLY change is to move the table from outside main to inside main.
// error: initializer element is not constant { Mammals, (int[]){Human, Elephant, Horse}, 3 },
//
static classification_t classifications[] = {
{ Mammals, (int[]){Human, Elephant, Horse}, 3 },
{ Amphibians, (int[]){Frog, Salamander}, 2 },
{ Avians, (int[]){Eagle, Sparrow, Duck}, 3 },
{ Fish, (int[]){Salmon, Carp, Tuna}, 3 }
};
for(int i=0; i<4; ++i)
{
printf("Category %d has %d examples\n", classifications[i].category, classifications[i].num_examples);
}
return 0;
}
It is not at all clear to me why the array initialization works in the first example, but not the second one.
Is there a simple technique to make this big table static, but declared within a function scope?
As one commenter pointed out, the entire problem can be described more directly like this:
static int* foo = (int[]) { 3, 4, 5 };
// This is Valid; apparently, the anonymous array is a constant-pointer
int main()
{
static int* foo = (int[]) { 3, 4, 5 };
// This is NOT valid; the anonymous array is likely on the stack.
static int* foo = (static int[]) { 3, 4, 5 };
// This is NOT valid; the static keyword is invalid before int[]
// But it was an attempt to make the array "static"
}
Is there some way to declare a static, anonymous array within a function?
The difference is the storage duration of the compound literals used as initializers of static objects.
When you are using them in the file scope they have static storage duration and may be used as constant expressions to initialize objects,
When you are using them within main (in block scope) then they have automatic storage duration that is they may not be used as constant expressions to initialize objects with static storage duration.
From the C Standard )6.6 Constant expressions)
and
Pay attention to that the compound literals used as initializers of your array and having array types as for example
are implicitly converted to pointers to their first elements.