13

I have a struct like this:

struct foobar {
    int i;
    char *word;
};

I know this will work:

struct foobar {
    int i;
    char *word;
};
struct foobar three = {3, "three"};

Why doesn't the following work though?

struct foobar {
    int i;
    char *word;
} three;
three = {3, "three"};

It will give the error: expected expression before ‘{’ token.

6
  • 1
    Your second example is an assignment, not an initialization. Commented Apr 26, 2017 at 19:35
  • 1
    This kind of assignment is not allowed? Commented Apr 26, 2017 at 19:36
  • Is this C or C++? Don't use both tags. Commented Apr 26, 2017 at 19:38
  • 1
    That kind of assignment is allowed in C++, but not C. Commented Apr 26, 2017 at 19:40
  • Thanks. Do you guys know what "expected expression" mean here? Commented Apr 26, 2017 at 19:42

4 Answers 4

21

It doesn't work, because C doesn't know what type {3, "three"} should be of; C doesn't look at the left side of the "=" operator to guess your type, so you don't have any type information there. With C99 you can use a compound literal for this:

three = (struct foobar) { 3, "three" };

The cast gives the type, the values in the curly brackets the initiallizer. The result is than assigned to your variable three.

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

4 Comments

This really works. So basically, you are doing an assignment and this assignment looks like an initialization. Am I right about this?
@JianglsAtWar: You can basically think of the compound literal to be an anonymous object with automatic storage class (i.e. valid for the current block). First you initialize this anonymous object, next it will be copied to "three". Likely you can trust your compiler to silently optimize away the overhead of creating the anonymous object.
i have a case where casting the type with the struct keyword works, and another where it doesn't ("a compount littereal of type Foo is not allowed" - static checker, or also "variable has incomplete type 'struct MQTTClient_createOptions' - clang error). can you explain why? Is it because the type contains an array? It seems just dropping struct works anyway (at least with Clang here in my env).
@Tchakabam: Without seeing the code, I think the clang message telling you the reason. In the scope you are trying to initialize your struct, the struct is just declared, but not defined. I.e. you have something like "struct MQTTClient_createOptions;" somewhere in your included headers, but the complete struct definition with all its members is not visible. Therefore the struct has an incomplete type. You will be able to get an pointer to this type, but can't instantiate a variable of this struct.
11

"initialization" and "assignment", though having quite similar syntax, are two different things with different restrictions.

"Initialization" means to define the initial value of a variable right in the course of variable definition. Assignment, in contrast, assigns a value to a variable defined elsewhere in the program.

C does not support assignment of values to variables of type struct or array, but it supports initialization of variables of these types:

struct foobar three = {3, "three"} is an initialization, since the value is defined together with the variable definition. This is supported in C and in C++.

struct foobar three; three = {3, "three"} in contrast, is an assignment, because the variable is first declared, but the value is assigned in a separate statement. This is not supported in C, but would be supported in C++.

1 Comment

Actually, C supports assignments for structs. There is no problem with struct foobar three = {3, "a"}; struct foobar b; b = three;.
1

It looks like you are trying to use the so-called "instantiation syntax" here. Unfortunately, this only works at the very moment you declare the variable!

If you do it after declaration (like in your example), you have to use one of the more cumbersome ways.

To clarify, this is how it would work:

struct foobar {
    int i;
    char *word;
    } three = {3, "three"};

Comments

-3

The reason why this:

struct foobar {
    int i;
    char *word;
} three;
three = {3, "three"};

doesn't work is because you did not typedef the struct.

You want to do:

typedef struct foobar {
      int i;
      char *word;
} three;

Once you typedef, three now becomes your new datatype like int or char. If you want to work with three you want to do this:

three x = {3, "three"};

You initialize a variable, such as x, and assign it {3, "three"}

2 Comments

Have you tried compiling it and using printf x.i? #include <stdio.h> int main (void) { typedef struct foobar { int i; char *word; }three; three x = {3, "three"}; printf("%s\n", x.word); return (0); }
Have you tried compiling OP's second code snippet? It works just fine without typedef. The question is about why it doesn't work to separate the assignment from the initialization. You would see the same error if you change your last line to three x; x = {3, "three"};.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.