Что возвращает задание?

#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; . Нынешние и предыдущие значения никогда не должны иметь разных типов, в то время как я могу использовать a float для своего роста вместо an int . Просто еще один уровень намерения, который можно уловить.

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:

  1. Присвоьте значение 2 i
  2. Оцените переменную 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) действительно не имеет никакой ценности, но это не бесполезно, хотя многие программисты считают, что это не стоит усилий.