#c
Вопрос:
Почему выражение i = 2
возвращает 2? На каком правиле это основано?
printf("%dn", i = 2 ); /* prints 2 */
Я нахожусь в домене C после долгого времени, проведенного в Java/C#. Простите мое невежество.
Ответ №1:
Он оценивается 2
как, потому что так определяет стандарт. Из стандарта C11, раздел 6.5.16:
Выражение присваивания имеет значение левого операнда после присваивания
Это значит позволять такие вещи, как это:
a = b = c;
(хотя есть некоторые споры о том, является ли подобный код хорошей вещью или нет.)
Кстати, это поведение воспроизводится в Java (и я готов поспорить, что то же самое происходит и в C#).
Комментарии:
1. Как правило, я согласен с этим, когда
a
иb
на самом деле одно и то же, а не просто одно и то же значение. Я использую те же рассуждения, чтобы выбрать междуint presentValue, previousValue;
противint myAge; int myHeight;
. Нынешние и предыдущие значения никогда не должны иметь разных типов, в то время как я могу использовать afloat
для своего роста вместо anint
. Просто еще один уровень намерения, который можно уловить.2. Обновлена ссылка @SurajJain на C11. То, что эта конструкция также позволяет (гораздо более полезно)
if ( ( ptr = func() ) != NULL )
…
Ответ №2:
Правило состоит в том, чтобы возвращать правый операнд =
преобразованного в тип переменной, которой он присвоен.
int a;
float b;
a = b = 4.5; // 4.5 is a double, it gets converted to float and stored into b
// this returns a float which is converted to an int and stored in a
// the whole expression returns an int
Комментарии:
1. Не могли бы вы предоставить справку? Оли Чарльсворт говорит, что в C99 это значение левого операнда, так что это будет отличаться от C ?
2. Итак, это противоречит вашему ответу (rvalue => значение lvalue, правая сторона =>> левая сторона).
3. В этом нет никакого реального противоречия. «значение r, преобразованное в тип переменной» — это именно то, чем будет переменная (значение lvalue) после присвоения. Два способа сказать одно и то же. Правило «значение после присвоения» также применяется как есть для
=
etc.4. IIRC здесь действительно есть разница —
b = 4.5
вычисляется значение4.5
в C, но в C это значение lvalue, на которое ссылаетсяb
. Трудное значение для фактического использования в LHS задания, так как, например(a = b) = 1
, в любом случае является UB из-за отсутствия точки последовательности между двумя модификациямиa
. Но я думаю , что в C вы можете взять адресamp;(a = 1)
, и это адресa
, а в C вы не можете. Кто-нибудь, поправьте меня, если я ошибаюсь.
Ответ №3:
Сначала он рассматривает выражение, а затем выводит крайнюю левую переменную.
пример:
int x,y=10,z=5;
printf("%dn", x=y z ); // firstly it calculates value of (y z) secondly puts it in x thirdly prints x
Примечание:
x
является постфиксом и x
является префиксом, поэтому:
int x=4 , y=8 ;
printf("%dn", x ); // prints 4
printf("%dn", x ); // prints 5
printf("%dn", y ); // prints 9
Комментарии:
1. вы знаете, что вычисления выполняются справа налево. Вычисления могут быть выполнены в любом порядке, включая задания. Значения аргументов вычисляются до вызова функции, но это, пожалуй, единственное предположение, которое вы можете сделать. Важно понять концепцию точки последовательности.
2. Ты прав, парень! но я имею в виду простые, такие как x=y z, я отредактировал ответ, спасибо.
Ответ №4:
- Присвоьте значение 2 i
- Оцените переменную i и отобразите ее
Ответ №5:
В C (почти) все выражения имеют 2 вещи
1) значение
2) побочный эффект
Значение выражения
2
есть 2
; его побочный эффект — «нет».;
Значение выражения
i = 2
является 2
; его побочным эффектом является «изменение значения в объекте с именем i
на 2″.;
Комментарии:
1. За 50% возможных выражений C
(void)
следует другое выражение (для определенных значений «доля бесконечного множества»). Они считают, что имеют значение, или нет? 😉2. Нет,
(void)
выражения не имеют значения. Например: выражениеfree(pointer)
не имеет значения.3. @pmg:
free(pointer)
действительно не имеет никакой ценности, но это не бесполезно, хотя многие программисты считают, что это не стоит усилий.