7

I'm trying to create an RPG-esque inventory, my inventory contains a type 'sword' which is an array. Here's the code for my sword struct:

typedef struct
{
    char weaponName[35];
    int damage;
    int rarity;
    float price;

} sword;

Here's the one for the inventory:

typedef struct
{
    sword SwordInvent[size];
} inventory;

I tried to initialize the SwordInvent array in the main function but it ends up with an error.

[Error] expected expression before '{' token

main()
{
    inventory inv;
    inv.SwordInvent[0] = {"Paper Sword", 1, 1, 1};
}

Can anyone be kind enough to help me get out of this hole? :(

EDIT I could not thank you all enough! I wasn't really expecting to get this much of help! Seriously, thank you!

2
  • Try inventory inv = {{"Paper Sword",1,1,1}}. Commented Sep 29, 2016 at 14:25
  • That's not an initializer, but an assignment. Commented Sep 29, 2016 at 14:32

5 Answers 5

5

You can't just start listing stuff inside braces and have the compiler magically figure out what you want. It doesn't work like that, except with initializers. Initializers, e.g.

const sword excalibur = { "Excalibur!", INT_MAX, INT_MAX, FLT_MAX };

are different from assignment. With initializers, it's assumed that the right-hand side is going to match the left-hand side, since it's an initializer. Also, they existed longbefore compound literals, so way back this was all you could to with = and structures.

Your code (assignment) is a bit like this:

float x;
x = 1 / 2;

This does not do a floating-point division, since 1 and 2 are both integers; the compiler does not figure out that this should have a floating point result based on the type of the left-hand side (and no, with an initializer for a float it still doesn't help, float x = 1 / 2; will not assign 0.5 but 0; end of analogy).

The same is true (kind of) for your brace-list assignment. There needs to be something on the right hand side that indicates the type of the braced list.

Thus, you need to use the compound literal syntax:

inv.SwordInvent[0] = (sword) {"Paper Sword",1,1,1};

Also, your sword is not an array, it's a struct.

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

8 Comments

Except it sorta does work like that in an initializer, which I suspect is where the OP's confusion arises. That, and the fact that he has an assignment, not an initialization, and the two are different.
@JohnBollinger Good point. I've edited to clarify, I hope. Thanks.
The outer parentheses are unnecessary.
@JohnBollinger: A compound literal is not immutable and it is an lvalue.
@Olaf Right, thanks. I grabbed the first example from GCC's documentation, without double-checking. Fixed.
|
5

When you write:

inventory inv;
inv.SwordInvent[0]={"Paper Sword",1,1,1};

you are not doing initialization; you are doing (attempting to do) an assignment. Initialization would look like:

inventory inv = { { "Paper Sword", 1, 1, 1 } };

Also note that this initializes all elements of the inv variable; the ones without an explicit value are zeroed.

If you want to do assignment, use a compound literal (C99 or later):

inventory inv;
inv.SwordInvent[0] = (sword){ "Paper Sword", 1, 1, 1 };

Note that after this executes, only element 0 of the array has values assigned; all the other elements are still uninitialized (have indeterminate values). So, unless size == 1, there's a fairly big difference between the initialization and the assignment.

2 Comments

"Note that this only initializes element 0 of the array;" It's not an initializer if it's not in a declaration.
@Rhymoid: I've changed the wording, but I was not claiming that the assignment (third paragraph of code) was an initializer. I was stating that after the assignment, one element (element 0) of the array in the structure has values assigned — leaving the remainder of the elements uninitialized. Given that it's a local variable in main(), that means the values are indeterminate — if it was a variable defined at file scope, (a) assignment would not be feasible on the next line, and (b) all the elements would be initialized, of course.
2

You have to specify the type before assignment:

inv.SwordInvent[0] = (sword) { "Paper Sword", 1, 1, 1 };

2 Comments

... to make it a compound literal, which in turn can be assigned.
I assume you mean "assignment" and not "assignation"? The first definition Google gives for "assignation" is "an appointment to meet someone in secret, typically one made by lovers."
1

You can do it at the declaration line.


The simplest way to emulate what you're trying to do is:

inventory inv = {{"Paper Sword",1,1,1}};

A more general (and perhaps readable) manner would be:

inventory inv =
{
    .SwordInvent =
    {
        {
            .weaponName = "Paper Sword",
            .damage = 1,
            .rarity = 1,
            .price  = 1
        }
    }
};

If you want to initialize, say, two entries in the array, then you could use something like:

inventory inv =
{
    .SwordInvent =
    {
        {
            .weaponName = "Paper Sword",
            .damage = 1,
            .rarity = 1,
            .price  = 1
        },
        {
            .weaponName = "Light Saber",
            .damage = 100,
            .rarity = 100,
            .price  = 100
        }
    }
};

9 Comments

Thank you for the input! I didn't know I could do it this way—makes things easier! :)
With designated initializers, the designators do not have to be in the same sequence as the members are defined in the structure. The light sabre could be initialized with: { .price = 100.001 .damage = 100, .rarity = 100, .weaponName = "Light Sabre", } and the effect is the same as if the designators were in the sequence of members in the structure. (And don't worry: it's just an English speaker fixing Americanized spellings to suit himself.)
@JonathanLeffler: Of course, but if you were ever to remove those designated initializers (just the member names, not the actual values), then the order would matter. And I've seen some compilers which do not accept this syntax (for whatever reason), in which case, porting your code could become an extremely tedious procedure. (Not worried, I'm neither English nor American, and had to look up Light Saber on Google to be sure that I was spelling it correctly (and as you know - Google is mostly American))...
@barakmanos I created a new struct to have all the armor parts typedef struct { helmet helm; suit sut; gloves glabs; boots buts; }armor; and I added it to my inventory struct typedef struct { sword SwordInvent[size]; armor ArmorInvent[size]; }inventory; I initialized it the same way you showed me, but it doesn't seem to work . inventory inv = { .ArmorInvent.helm = { { .helmName = "[Default]Paper Helmet", .def = 1, .rarity = 1, .price = 1 } } }; What am I doing wrong?
@ChocoFernandez: How exactly do you expect me to answer this question when your definitions for helmet, suit, gloves and boots are missing???
|
1
inv.SwordInvent[0]={"Paper Sword",1,1,1};

Such assignment is illegal. Expression at the right side of = should have proper type. The easiest way is to use compound literal (as mentioned in other answers):

inv.SwordInvent[0] = (sword){"Paper Sword",1,1,1};

Alternatively you can use next initialization:

inventory inv = {
    {
        {"Paper Sword",1,1,1},  /* init SwordInvent[0] */
        {"Paper Sword",1,1,1},  /* init SwordInvent[1] */
        /* ... */
    }
};

This variant conforms to C89, that may be useful if your compiler doesn't support newest language features.

4 Comments

It isn't an initializer.
@JonathanLeffler According to N1570 6.7.9 Initialization, {"Paper Sword",1,1,1} appears to be an initializer, doesn't it?
Not really; you don't have a type on the line described as an initializer (inv.SwordInvent[0]={"Paper Sword",1,1,1};). Initializers can only appear as part of a variable definition. This is an attempted assignment. You only have to recharacterize the code in the question; the rest of what you say is OK, though you're missing one level of braces in the initialization you suggest.
@JonathanLeffler My bad. Thanks :-)

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.