Унарный: почему унарное поведение в c # зависит от c / c ++

Возможный дубликат:
Неопределенный, неуказанный и определенный реализацией поведение
Неопределенное поведение и точки последовательности
Поведение оператора приращения до и после в C, C ++, Java и C #

У меня есть этот фрагмент кода:

int x = 2;
int y = x + 4 * ++x;
// what is y???

И когда я скомпилирую и протестирую его в c / c ++, я получу:

// C/C++
y is 15

Но через c # я получу

// C#
y is 14

ПОЧЕМУ?


В состав IL входит:

locals init ([0] int32 x,
[1] int32 y)
IL_0000: nop
IL_0001: ldc.i4.2
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: ldc.i4.4
IL_0005: ldloc.0
IL_0006: ldc.i4.1
IL_0007: add
IL_0008: dup
IL_0009: stloc.0
IL_000a: mul
IL_000b: add
IL_000c: stloc.1
IL_000d: ldloca.s y

person amiry jd    schedule 23.10.2011    source источник
comment
Так как. кажется мне совершенно хорошим ответом.   -  person R. Martinho Fernandes    schedule 23.10.2011
comment
@David добавил дублирующую ссылку, которая касается этого :)   -  person R. Martinho Fernandes    schedule 23.10.2011
comment
Спасибо, @ R.MartinhoFernandes, я удалил комментарий и согласен с тем, что вопрос дублируется.   -  person David Rodríguez - dribeas    schedule 23.10.2011


Ответы (2)


int y = x + 4 * ++x;

В C и C ++ порядок оценки каждого операнда не определен, что означает, что либо x, либо 4*++x могут оцениваться раньше другого. Поскольку порядок оценки операндов не указан, результат всего выражения не указан.

Если x оценивается до 4*++x, то y будет вычисляться как:

int y = x + 4 * ++x; //original

int y = 2 + 4 * ++x  //evaluate x first
      = 2 + (4 * 3)  //evaluate 4 *++x then
      = 14;

Аналогично, если 4*++x оценивается до x, тогда

int y = x + 4 * ++x; //original

int y = x + (4*3)  //evaluate 4 * ++x first
      = 3 + 12   //evaluate x then  (x is incremented)
      = 15;

В C # операнды должны оцениваться слева направо, поэтому вы всегда получаете первое поведение, дающее в результате 14.

person Nawaz    schedule 23.10.2011
comment
Разве это не неопределенное поведение, потому что вы читаете и изменяете x в одном и том же выражении, без разделительных точек последовательности? - person jalf; 23.10.2011
comment
Не просто не указано, UB в этом случае из-за того, что упомянул @jalf - person Praetorian; 23.10.2011
comment
@jalf: не вызывает ли изменение объекта более одного раза без промежуточной точки последовательности UB? - person Nawaz; 23.10.2011
comment
@Nawaz: изменение несколько раз или изменение, а также чтение. Как только вы его измените, вы не сможете делать с ним больше ничего в этом выражении. - person jalf; 23.10.2011
comment
Я не могу понять, почему у вас 3 голоса "за" !!!!! Ваш ответ настолько прост и не имеет никакого отношения к Вопросу! - person amiry jd; 23.10.2011
comment
@Javad_Amiry, почему это не имеет отношения к вопросу? Это объясняет результат, который вы получаете на C ++. В нем также объяснялось поведение C # в предыдущей версии, но оно было отредактировано :( - person R. Martinho Fernandes; 23.10.2011
comment
Да, я вижу ваше обновление только сейчас. Но как насчет стандартов? Разве C # не против обычных и стандартных операндов? То же, что c/c++? Я думаю, это может вызвать некоторые логические ошибки у двуязычных программистов. Не так ли? (Я пишу по-английски так плохо): извините, если грамматика моих предложений неправильная) - person amiry jd; 23.10.2011
comment
@Javad C # следует стандарту C #, а C ++ следует стандарту C ++. Эти два разные. Это вызывает проблемы только у программистов, которые не знают оба языка, и поэтому не должны программировать на обоих языках. В любом случае следует избегать некрасивого кода. - person R. Martinho Fernandes; 23.10.2011
comment
Я согласен с вами C# follows the C# standard and C++ follows the C++ standard. The two are different.. Но я не знаю, как мне задать свой вопрос. Однако есть c-family языков, хммм Х не знаю, как спросить): - person amiry jd; 23.10.2011
comment
@Javad: семейство языков C - это очень вводящий в заблуждение термин, используемый для обозначения различных языков, которые имеют схожий синтаксис, но полностью отличаются друг от друга. Не позволяйте этому запутаться. Рассматривайте C, C ++ и C # как совершенно разные языки, потому что они такие. Просто они похожи по синтаксису. - person R. Martinho Fernandes; 23.10.2011

Фактически, в C ++ вы просто получаете неопределенное поведение, поскольку порядок оценки выражений не всегда указывается, поэтому неясно, будет ли при первом использовании x считываться старое или новое значение. Оба варианта возможны, и на самом деле возможно все, что угодно, потому что в стандарте прямо сказано, что не определено, что происходит.

C #, как безопасный язык, не может допустить такой ситуации и, таким образом, более строго определяет порядок оценки.

person Sebastian Redl    schedule 23.10.2011
comment
Порядок оценки не указан. Если бы это было undefined, вы не смогли бы написать какую-либо полезную программу на C ++. - person R. Martinho Fernandes; 23.10.2011
comment
Исправлена ​​эта деталь. Однако основная проблема заключается в том, что неупорядоченное чтение и запись в одну и ту же переменную является неопределенным поведением; неустановленный порядок оценки как раз и является причиной этого. - person Sebastian Redl; 23.10.2011
comment
@ R.MartinhoFernandes: Порядок оценки не указан, но показанный здесь код все еще не определен. :) - person jalf; 23.10.2011