2013-08-23 2 views
-2
public class Test 
{ 
    public static void main(String[] args) { 
     int i = 10; 
     i = i++; 
     System.out.println("value of i is : " + i); 
    } 
} 

Выход есть: 10Пожалуйста, объясните, почему Java и C дают разные ответы на этот код

Когда я выполнил аналогичный код в C, выход является 11.

+2

Ну, разница между вашим ожиданием и тем, что происходит, очевидно, потому что ваше ожидание того, что 'i = i ++' делает, неверно. Что еще сказать? Чтобы действительно ответить на этот вопрос, нам нужно знать, почему * вы думаете, что выход должен быть 10? – Raedwald

+0

Процитированный dup не распространяется на Java вообще, за исключением передачи ссылки и определенно не объясняет разницу между Java и C в отношении этого примера и их подходов к неопределенным поведением и точкам последовательности. –

ответ

14

Что касается C это undefined behavior, поскольку вы пытаетесь изменить ту же переменную более одного раза в одной и той же sequence point на этой линии: пункт 2

i = i++; 

draft C99 standard в разделе 6.5говорит:

Между предыдущей и следующей точкой последовательности объект должен иметь сохраненное значение изменен не более одного раза путем оценки выражения. Кроме того, предварительное значение должно быть считано только для определения значения, которое необходимо сохранить.

Это хорошо определено в Java, которая не имеет ту же концепцию, что точка последовательности C делает и спецификации языка Ява (JLS) выходит из своего пути, чтобы обеспечить такие операции определены. Раздел 15.7 из JLS говорит:

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

и раздел 15.7.2 говорит:

Язык программирования Java также гарантирует, что каждый операнд оператора (за исключением условных операторов & &, ||, и :) ? представляется полностью оцененной до того, как выполняется какая-либо часть самой операции.

Обратите внимание, что C не определяет порядок оценки, в основном, чтобы дать компилятору better options for optimization. Из проекта стандарта раздела 6.5пункта 3:

Группировки операторов и операндов обозначенные syntax.74) За исключением случаев, указанными позже (для вызова функции(), & &, || ,?: и запятые), , порядок оценки подвыражений и порядок, в котором происходят побочные эффекты, не определены.

Update

Если вы хотите обсуждение на некоторые различия в философии между Java и C по отношению к неопределенному поведению у вас есть Undefined behavior is a design decision и Undefined behaviour in Java.

+0

Что такое C++? AFAIK - порядок, в котором выполняются операторы. – Paranaix

+1

@Paranaix Это поведение не определено в C++, а также в разделе 15 раздела «1.9» в проекте стандарта. –

+0

Но не могу ли он быть записан как 'i = i.operator ++()'? Я хорошо знаю, что 'i' не является объектом, но я пытаюсь объяснить свою точку зрения этим псевдокодом. – Paranaix

5

Это Undefined behaviour в C. Отсутствие sequence point.

+2

Это также определено поведение в Java, где значение переменной сохраняется, переменная увеличивается и старое значение записывается обратно. http://stackoverflow.com/questions/7911776/what-is-x-after-x-x – chrylis

0

В Java, i = i++; пост ++ будет увеличивать значение после этого шага. Но здесь, в момент присвоения i++, i, i по-прежнему 10, так что вы получаете 10. Но в C это может отличаться от Java. Если вы используете i=++i в коде Java, вы получите 11.

0

Java и C - это разные языки с разными правилами. В C точный порядок оценки выражений и применения побочных эффектов - неуказанный; для выражения, такого как i = i++, нет гарантии, что побочный эффект оператора ++ будет применен до назначения. Результат будет зависеть от платформы, настроек оптимизации, даже окружающего кода. Поведение: undefined; компилятор может справиться с ситуацией по своему усмотрению, что включает в себя создание неожиданного результата.

Java, OTOH, задает строгий порядок оценки, и эти побочные эффекты применяются немедленно, поэтому выражение четко определено.

Смежные вопросы