проблема с присвоением значения объединенному полю структуры - PullRequest
0 голосов
/ 05 октября 2019

Я новичок здесь, надеюсь, что смогу помочь. После изучения урока о structs и unions я практикую то, что узнал, и хочу объединить две идеи. Но я получаю сообщение об ошибке, которое пытался решить пару часов, но безуспешно.

Код:

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};

my gcc compiiler (используя codeBlocks) кричит мне:

ошибка:ожидаемое выражение перед '{' token |

и, что бы я ни пытался, это не помогло.

Пожалуйста, помогите.

1 Ответ

1 голос
/ 05 октября 2019

Присвоение структуре

Синтаксис использования фигурных скобок ({ .... }) со списком начальных значений для структуры может использоваться только при определении структуры, например:

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 };

В первой из них внутренние скобки указывают, что мы предоставляем начальное значение для подобъекта основного объекта - для объединения amount внутри orangeProduct. Как показывает вторая строка, это не требуется, поскольку, если фигурные скобки опущены, компилятор примет несгруппированные начальные значения и в любом случае назначит их членам подобъектов. Тем не менее, полезно явно включать фигурные скобки, так как это позволяет избежать ошибок в более сложных агрегатах и ​​помочь донести намерения до читателей.

В третьей и четвертой формах показано, что мы можем инициализировать членов, используя их имена. Эта форма называется назначенными инициализаторами. Они наиболее полезны, когда вы пропускаете элементы в структуре или хотите инициализировать элемент объединения, отличный от первого в списке.

Однако другой ответ предложил это неверное утверждение:

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

Это неправильно, потому что productOrdered.theAmount.individual = 13 не просто начальное значение;это выражение присваивания. Назначается от 13 до productOrdered.theAmount.individual. Проблема в том, что весь оператор также присваивает значения productOrdered, в том числе productOrdered.theAmount.individual. Это нарушает правило в C 2018 6.5 2, которое гласит:

Если побочный эффект на скалярном объекте не секвенирован относительно другого побочного эффекта на том же скалярном объекте или вычисления значения с использованиемзначение того же скалярного объекта, поведение не определено…

Два присваивания 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)
...