将值分配给结构的联合字段的问题

problem with assigning value to a unionized field of a struct

我是新来的,希望能得到一些帮助。 在做了一个关于structsunions的教程后,我实践了所学,想把两个想法结合起来。但是我得到一个错误,我已经尝试解决了几个小时,但没有任何运气。

密码是:

void main(){

    typedef enum {INDIV, OUNCE, POUND } quantity;

    typedef union{

        short individual;
        float pound;
        float ounce;

    } amount;

    typedef struct{

        char *brand;
        amount theAmount;

    } orangeProduct;

    orangeProduct productOrdered;

    quantity quantityType = OUNCE;

    switch(quantityType)
    {
        case INDIV:
            productOrdered = {"Chiquita", .theAmount.individual = 13 };
            printf("You bought %d oranges\n\n", productOrdered.theAmount.individual)
            break;

    }
}

我还有其他案例,但这没关系:如果我解决了第一个问题,我就会解决所有问题。 目标是拥有可以容纳橙子品牌的结构,并为每个品牌容纳购买的数量、正确的重量类型。

问题在于行:

productOrdered = {"Chiquita", productOrdered.theAmount.individual = 13 };

我的gcc compiiler(使用codeBlocks)对我大喊:

error: expected expression before '{' token|

而且,无论我怎样尝试,都无济于事。

请帮忙。

分配给结构

使用大括号 ({ .... }) 和结构初始值列表的语法只能在定义结构时使用,如:

orangeProduct productOrdered = { "Chiquita", { 13 } };

您不能在作业中使用它;此语句没有正确的语法:

productOrdered = { "Chiquita", { 13 } };

有两种方法可以为结构分配值,而不是在定义时初始化它。一种是单独分配给每个成员:

productOrdered.brand = "Chiquita";
productOrdered.theAmount.individual = 13;

另一种是从另一个结构复制过来的:

productOrdered = SomeOtherProduct;

我们可以将上面的代码与另一个称为 复合文字 的 C 功能一起使用。可以在表达式中使用复合文字来提供一个对象而不用给它一个名字。复合文字的一般形式是:

(type) { initial values... }

虽然(type)看起来像演员表,其实不然。此语法定义了一个对象,它可以对声明中使用的初始值使用相同的语法。这意味着我们可以初始化复合文字并将其分配给结构:

productOrdered = (orangeProduct) { "Chiquita", { 13 } };

关于分配给结构的其他注意事项

以下所有都具有相同的效果:

productOrdered = (orangeProduct) { "Chiquita", { 13 } };
productOrdered = (orangeProduct) { "Chiquita", 13 };
productOrdered = (orangeProduct) { "Chiquita", { .individual = 13 } };
productOrdered = (orangeProduct) { "Chiquita", .theAmount.individual = 13 };

在其中的第一个中,内部大括号表示我们正在为主对象的子对象提供初始值——为 orangeProduct 内的联合 amount。如第二行所示,这不是必需的,因为如果省略大括号,编译器将采用未分组的初始值并将它们分配给子对象的成员。但是,最好明确包含大括号,因为它可以避免在更复杂的聚合中出现错误,并有助于向人类读者传达意图。

第三和第四种形式表明我们可以使用他们的名字来初始成员。这种形式称为指定初始值设定项。当您跳过结构中的成员或想要初始化除第一个列出的成员以外的联合成员时,它们最有用。

然而,另一个答案提出了这个不正确的陈述:

productOrdered = (orangeProduct){"Chiquita", productOrdered.theAmount.individual = 13 }

这是错误的,因为 productOrdered.theAmount.individual = 13 不仅仅是一个初始值;它是一个赋值表达式。它将 13 分配给 productOrdered.theAmount.individual。问题在于整个语句还为 productOrdered 赋值,包括 productOrdered.theAmount.individual。这违反了 C 2018 6.5 2 中的规则,即:

If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined…

productOrdered.theAmount.individual 的两个赋值是无序的,因为 C 标准中没有规则说明赋值相对于彼此发生的时间。 (当赋值表达式更新对象的值时,这称为副作用,它不是表达式主要求值操作的一部分。)

其他注意事项

main 应该用 int main(void)int main(int argc, char *argv) 声明,而不是 void main()。它也可以用您的 C 实现允许的特定形式声明。

在您的代码中包含 #include <stdio.h> 以声明 printf

在这一行添加一个分号:

printf("You bought %d oranges\n\n", productOrdered.theAmount.individual)