Yes, it is legal, as long as you are initializing an object with automatic storage duration (as in your example). For objects with static storage duration that would not be legal, since such objects allow only constant expressions in their initializers.
Also keep in mind though that in C evaluations of initializer expressions are indeterminately sequenced with respect to one another. Which means that if you have multiple function calls among your initializers and these functions' results depend on some shared state, these initalizers might behave unpredictably
int foo()
{
static int a;
return ++a;
}
int main()
{
struct { int x, y; } s = { foo(), foo() };
/* Can be `{ 1, 2 }` or `{ 2, 1 }`... */
}
With regard to portability, one can note that C89/90 did not permit this (formally in C89/90 all {}-enclosed initializers has to be constant expressions, even for automatic objects), but most popular C89/90 compilers supported this regardless.
gcc] as you've presented it. However, if you madema global (file scope variable), it will not. The compiler flagshtonl: error: initializer element is not constant. I believe most C compilers will behave in a similar manner. Side note: C++ does allow this at global scope [in your example, it warns aboutntonlbeing unsigned vs the signedint c, but this would be easy enough to fix]