#c #operators #operator-precedence #conditional-operator
#c #операторы #оператор-приоритет #условный оператор
Вопрос:
Я читаю книгу по программированию на c и столкнулся с этим примером:
a<=20?b=30:c=30;
Мне просто нужно использовать число 30 один раз. Решение в книге было
((a<=20)?amp;b:amp;c)=30);
Когда я пытаюсь запустить это, я получаю следующую ошибку:
значение lvalue требуется в качестве левого операнда присваивания.
Кажется, что там отсутствует одна из круглых скобок, но я не знаю, где.
Не могли бы вы сказать мне, как я могу это исправить?
Комментарии:
1. это выглядит как бессмысленное упражнение
2.
*((a<=20)?amp;b:amp;c)=30;
3. Вы могли бы рассмотреть расширения GCC
Ответ №1:
предположим, что a и b являются числами одного и того же типа, просто сделайте
*((a <= 20) ? amp;b : amp;c) = 30;
для получения адресов a и b необходимо разыменовать (‘*’), чтобы иметь значение lvalue
из замечания @Vrintle примечание, которое вы также можете сделать на C
((a<=20)?b:c)=30;
компилятор знает, что форма является значением lvalue, поэтому используются не значения b и c, а их ссылки
Кажется, что там отсутствует одна из круглых скобок, но я не знаю, где.
в ((a<=20)?amp;b:amp;c)=30);
последнем ‘)’ нет соответствующего ‘(‘
Комментарии:
1. Разве это не было бы просто
(a<=20?b:c)=30;
хорошо?2. @Vrintle нет, потому что вы получаете значение b или c , так что это все равно, что писать
10=20
, требуется значение lvalue3. Кажется, все в порядке. Но я запустил его на TIO , cpp.sh и это не дало никаких ошибок. Почему так?
4. @Vrintle Я отредактировал свой ответ, спасибо за замечание, я просто просыпаюсь 😉
5. @Vrintle: он не дал ошибок при TIO или cpp.sh потому что вы скомпилировали его как C , а правила в C другие. В C
(a <= 20 ? b : c)
не является значением lvalue , поэтому оно не может быть левым операндом присваивания (в отсутствие расширения компилятора для языка). Согласно C 2018 6.3.2.1 2, значения lb
иc
преобразуются в значения в? :
выражении.
Ответ №2:
Для начала в C это выражение
a<=20?b=30:c=30
эквивалентно
( a<=20?b=30:c ) = 30
и компилятор выдаст ошибку, потому что левый операнд присваивания не равен lvalue .
Вы должны написать
a <= 20 ? b = 30 : ( c = 30 )
или для симметрии
a <= 20 ? ( b = 30 ) : ( c = 30 )
Вы имеете в виду следующее
*( a <= 20 ? amp;b : amp;c ) = 30;
Это уловка получения ссылки на объект в значении C, которое косвенно через указатель на объект. Сам указатель имеет значение rvalue, но, разыменовывая его, вы получаете значение lvalue указанного объекта.
В C вы могли бы написать просто
( a <= 20 ? b : c ) = 30;
потому что в этом случае оператор возвращает значение lvalue .
Между C и C есть разница в определении грамматики условного оператора.
В C это определяется как (6.5.15 Условный оператор)
conditional-expression:
logical-OR-expression
logical-OR-expression ? expression : conditional-expression
в то время как в C (C 14, 5.16 Условный оператор)
conditional-expression:
logical-or-expression
logical-or-expression ? expression : assignment-expression
Итак, в C допустимо исходное выражение, которое не скомпилировано компилятором C
a <= 20 ? b = 30 : c = 30
Комментарии:
1. вы уверены в приоритете?
2. @bolov Да, я уверен.
3. вы правы, я думал в режиме C . Не знал о разнице с C здесь.