2

I'm new to C and I'm trying to understand the syntax for compound literals. My question is similar to Initializing a pointer to compound literals in C but I don't think that answers it. If have a struct and a type defined as a pointer to the struct like this:

typedef struct thing *thing_t;
struct thing
{
    int id;
    char *name;
};

Then I can create a thing_t like this:

thing_t instance = & (struct thing) {
    .id = 1,
    .name = "A"
};

I was wondering if there is a way to initialize a thing_t without explicitly referring to struct thing, e.g. I tried this to see if it was valid syntax:

thing_t instance = (* thing_t) {
    .id = 1,
    .name = "A"
};

but the compiler errors. The compiler must "know" that the thing_t type holds a pointer to a thing, but is there syntax that allows to use the two interchangably in this context?

(I don't have a particular use case for this, I'm just trying to understand how the type and the struct are related).

3
  • 6
    Don't hide pointers behind typedefs. typedef struct thing thing_t; - problem solved. Commented Jun 14, 2018 at 14:41
  • Try -> instead of ., that may work Commented Jun 14, 2018 at 14:43
  • 2
    You might want to be careful with lifetime when using pointers to compound literals when you're new to C. Commented Jun 14, 2018 at 14:52

1 Answer 1

7

I was wondering if there is a way to initialize a thing_t without explicitly referring to struct thing, e.g. I tried this to see if it was valid syntax:

thing_t instance = (* thing_t) {
    .id = 1,
    .name = "A"
};

but the compiler errors. The compiler must "know" that the thing_t type holds a pointer to a thing,

Yes, it does, though it is poor form to define a type alias that hides pointer nature, as you have done, and it is especially poor form to do so with a name that does not somehow provide a clue about that.

but is there syntax that allows to use the two interchangably in this context?

The syntax for a compound literal includes the parenthesized type specifier. That's not a cast, it's part of the literal itself. You cannot do without it. If you want to avoid saying struct, though, then you can kill two birds with one stone by changing your type alias so that it describes the struct type itself, not a pointer to one:

typedef struct thing thing_t;
struct thing {
    int id;
    char *name;
};
thing_t *instance = & (thing_t) {
    .id = 1,
    .name = "A"
};

Not only does it work, but it's a heck of a lot clearer than your proposal. For example, the use of the & operator matches up with the clear declaration of variable instance as a pointer.

Sign up to request clarification or add additional context in comments.

4 Comments

Nice. I've been away from C for some time, and am learning C99 features more or less "by accretion." Thanks for the example of struct literal syntax and by-name member initialization. Both are nice additions to the C89/90 language.
This may be intended for file scope, but I do not see that explicitly stated in the question or this answer. Inside a function, a compound literal has automatic storage duration associated with its enclosing block, so its address should be used with caution.
That's a useful observation, @Eric. Indeed, the question does not touch on the lifetimes of the objects represented by compound literals, and I have answered only what was asked, but object lifetime is an important consideration for how a pointer such as the OP is obtaining may be used.
I'm just writing toy programs while I read through a book so it didn't matter in this case. Useful to know though, I hadn't thought about why it needed to be different from string literals. Thanks @JohnBollinger for your answer!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.