C - Creating an anonymous struct instance
Asked Answered
L

1

13

In this code, a structure is defined as follows:

typedef struct
{
    int line;
    int column;
} Pos;

And later used this way:

Pos get_pos ( int delta )
{
    ...

    return ( Pos ){ f->line, f->column + delta };
}

The line, return ( Pos ){ f->line, f->column + delta } seems to be creating an anonymous instance of the struct Pos with initialized values. What is this technique called and how does it work? Where can I learn more about it?

Leotie answered 8/2, 2019 at 4:18 Comment(4)
"Compound literal", since C99.Carl
C11 Standard - 6.5.2.5 Compound literalsPagano
stackoverflow.com/questions/tagged/… . There doesn't seem to be a canonical question, maybe this could be itJacktar
Thanks! Updated the question tag accordingly.Leotie
B
12

This is called a compound literal, and is documented in section 6.5.2.5 of the C standard.

An excerpt of this section is as follows:

3 A postfix expression that consists of a parenthesized type name followed by a brace- enclosed list of initializers is a compound literal. It provides an unnamed object whose value is given by the initializer list.

4 If the type name specifies an array of unknown size, the size is determined by the initializer list as specified in 6.7.9, and the type of the compound literal is that of the completed array type. Otherwise (when the type name specifies an object type), the type of the compound literal is that specified by the type name. In either case, the result is an lvalue.

5 The value of the compound literal is that of an unnamed object initialized by the initializer list. If the compound literal occurs outside the body of a function, the object has static storage duration; otherwise, it has automatic storage duration associated with the enclosing block.

In your case the compound literal is for a struct, but they can be created for arrays as well. Paragraph 8 gives an example:

8 EXAMPLE 1 The file scope definition

int *p = (int []){2, 4};

initializes p to point to the first element of an array of two ints, the first having the value two and the second, four. The expressions in this compound literal are required to be constant. The unnamed object has static storage duration.

Note also that a compound literal is an lvalue, which means you can take its address:

Pos *p = &( Pos ){ f->line, f->column + delta };

This object has a lifetime associated with its scope, meaning that once the scope ends the object no longer exists. So don't carry around its address after it goes out of scope.

You can also use a compound literal with a designated initializer:

return ( Pos ){ .line=f->line, .column=f->column + delta };
Banquette answered 8/2, 2019 at 4:26 Comment(2)
So it applies to all type (not only aggregates)?Mummify
@SomeName As it turns out, yes. int x = (int){4}; compiles, although there's not much use in using it for basic types.Banquette

© 2022 - 2024 — McMap. All rights reserved.