Странное поведение перечисления с тернарными операторами

Я писал очень простой тернарный оператор с одним из моих перечислений и наткнулся на очень странную ошибку (для меня ...). Учитывая этот фрагмент кода:

typedef enum
{
    first = 0,
    second,
    last
}myEnum;

myEnum myVar = first;

(myVar < second) ? myVar++ : myVar = last;

Компилятор отправил мне следующую ошибку:

ошибка: требуется lvalue как левый операнд присваивания

Где, как если бы я просто менял тернар на блок if / else, например:

if(myVar < second)
{
    myVar++;
}
else
{
    myVar = last;
}

Все компилируется и работает нормально. Может ли кто-нибудь объяснить, почему тот же самый код, написанный как троичный, не компилируется? Что мне не хватает?


person Asics    schedule 30.06.2014    source источник
comment
@dyp третья часть тернарного оператора не может быть выражением присваивания. Почему бы и нет? Если вы правильно заключите круглые скобки, это должно сработать (но может запутать читателя).   -  person glglgl    schedule 30.06.2014


Ответы (2)


Ваше выражение анализируется как:

( (myVar < second) ? myVar++ : myVar ) = last;

но, похоже, вы намеревались сделать:

(myVar < second) ? myVar++ : (myVar = last);

На самом деле это не совсем то, что требует стандарт (но многие компиляторы анализируют это таким образом), первое выражение должно фактически завершиться ошибкой по другой причине (синтаксическая ошибка, а не нарушение ограничения).

C99 6.5.15 говорит:

conditional-expression:
    logical-OR-expression
    logical-OR-expression ? expression : conditional-expression

и myVar = last не является условным-выражением, а выражением-присваиванием (C99 6.5.16):

assignment-expression:
    conditional-expression
    unary-expression assignment-operator assignment-expression

но (myVar < second) ? myVar++ : myVar не является унарным-выражением (см. C99 6.5.3) (но его версия в скобках будет такой, как я написал в моем первом фрагменте кода, см. C99 6.5.1).

HTH

person mafso    schedule 30.06.2014
comment
Вы правы, мое выражение лица было обработано не так, как я планировал. Довольно хитроумно, это должно быть одна из причин, по которой люди говорят, что следует избегать тройных ... Что такое HTH, кстати? - person Asics; 30.06.2014
comment
@Asics: «Надеюсь, это поможет». И еще: обратите внимание, что второй операнд тернарного оператора - это выражение, а не условное выражение, поэтому myVar>=second ? myVar=last : myVar++ работает ... - person mafso; 30.06.2014

То, что вы делаете и что вы пытаетесь сделать, несопоставимо.

Вот этот

if(myVar < second)
{
    myVar++;
}
else
{
    myVar = last;
}

переводится на

myVar = (myvar < second) ? myvar + 1 : last;

Если вы хотите полностью избавиться от побочных эффектов, вы также можете сделать

(myVar < second) ? myVar++ : (myVar = last);

но я не уверен, что это хороший стиль, так как он может запутать читателя относительно цели выражения.

person glglgl    schedule 30.06.2014