Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C - Creating an anonymous struct instance

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?

like image 725
Jet Blue Avatar asked Feb 08 '19 04:02

Jet Blue


1 Answers

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 };
like image 197
dbush Avatar answered Oct 24 '22 07:10

dbush