Reputation: 6464
Consider the following snippet:
struct my_struct {
int a;
int b;
int c;
};
void my_func(unsigned long x)
{
struct my_struct m[] = {
{ 0, 1, 2 },
{ 11, 22, htonl(x) },
{ 0x1, 0xa, 0xbb }
};
...
}
Is it legal/portable to call a function inside of a structure initialization block?
Upvotes: 2
Views: 1922
Reputation: 13134
Is it legal/portable to call a function inside of a structure initialization block?
[...]
| initializer-list: | designationopt initializer | initializer-list , designationopt initializer
~> initializer-lists consist of initializers
All the expressions in an initializer for an object that has static storage duration shall be constant expressions or string literals
~> Initializers consist of expressions. (constant-expr. for objects with static storage duration)
An expression is a sequence of operators and operands that specifies computation of a value, or that designates an object or a function, or that generates side effects, or that performs a combination thereof.
~> A function call is an expression.
Upvotes: 4
Reputation: 320421
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.
Upvotes: 5