Может ли кто-нибудь объяснить, почему выходы разные в C и Java? - PullRequest
3 голосов
/ 10 июля 2020
{
 public static void main(String[] args) {
     int a = 10;
     if (a == a--)
     System.out.println("first\t");
     
     a=10;
     if(a==--a)
     System.out.println("second\t");
     
 }
}

Для программы java вывод будет «первым», тогда как для программы C / C ++ - «вторым». Насколько мне известно, функциональность операций после исправления / исправления одинакова в обеих программах. Если кто-нибудь может пролить свет на лог c, было бы здорово, так как я новичок в кодировании.


int main()
{
   int a = 10;
   if(a==a--)
   
       printf("first\t");
   
   a=10;
   if(a==--a)
   
       printf("second\t");
   
}

Ответы [ 3 ]

4 голосов
/ 10 июля 2020

В java вы получаете гарантию, что всегда будете наблюдать этот код, выводящий First, и никогда Second.

В C / C ++ вы не получите таких гарантий. В зависимости от компилятора, архитектуры, ОС и фазы луны он, скорее всего, напечатает только First или Second, но я почти уверен, что C и C ++ spe c делают его «законным» для compiler / architecture / OS / phase-of-moon combo для вывода ОБЕИХ First и Second или даже ни одного.

См. порядок оценки правила для C ++: Учитывая некоторые Конструкция бинарного оператора: a x b, где a и b - выражения, а x - некоторый бинарный оператор, тогда сначала должны быть вычислены a и b, а затем оператор x применяется к полученным таким образом значениям. Если оператор явно не определяет порядок (что, например, делают операторы || и &&; они обещают выполнить короткое замыкание, то есть вообще не вычислять b, если a такое, что b не может повлиять на результат) - тогда компилятор C (++) может выдавать такой код, что b оценивается раньше, чем a, или наоборот.

C заполнено до краев с такими «musts» и «mays»: C spe c разработан для того, чтобы код C мог компилироваться на широком спектре микросхем с огромной свободой действий для компилятора для применения далеко идущих оптимизаций. Дошло до того, что простые примитивные типы данных имеют неопределенную битовую ширину.

В отличие от java, где почти все заблокировано: очень мало аспектов кода java, которые намеренно оставлены неопределенными, и компилятор находится «на рельсах» и очень сильно ограничен в том, какой байт-код ему разрешено генерировать (в java, оптимизации оставлены компилятору времени выполнения / хотспот, а не javac).

Вот почему на java spe c DOES явно определяет, как a x b должно быть разрешено: java spe c определяет, что независимо от оператора, a всегда должен оцениваться до вычисления b (если, как и в C, b вообще не оценивается из-за правил короткого замыкания).

Возвращение к Java Спецификация языка v7, SPE c явно диктует, что левая часть ДОЛЖНА быть оценена первой - и с тех пор это не изменилось (и я почти уверен, что так было с java 1.0, чего это стоит. Вероятно, это глава 15.7.1 в большинстве версий JLS).

3 голосов
/ 10 июля 2020

В C и C ++ выражение a == a-- и a == --a имеет вид undefined :

6.5 Выражения
.. .
2 Если побочный эффект для скалярного объекта не упорядочен относительно другого побочного эффекта для того же скалярного объекта или вычисления значения с использованием значения того же скалярного объекта, поведение не определено. Если существует несколько допустимых порядков подвыражений выражения, поведение не определено, если такой неупорядоченный побочный эффект возникает в любом из порядков. 84)
84) Этот абзац отображает неопределенный выражения операторов, такие как i = ++i + 1; a[i++] = i; при разрешении i = i + 1; a[i] = i;
C 2011 Онлайн-черновик

C не требует вычисления выражений отношения и равенства слева направо и не требует, чтобы побочный эффект операторов -- и ++ применялся сразу после вычисления. Результат a == a-- может различаться в зависимости от компилятора, оборудования и даже окружающего кода.

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

2 голосов
/ 10 июля 2020

В C (как кажется код во втором примере),

  1. Порядок оценки подвыражений не указан, и

  2. Между операндами оператора == нет точки последовательности.

Таким образом, если приращение a в if (a == a++) или уменьшение a в if (a == a--) происходит до того, как сравнение с a само не определено.

Результат вызывает неопределенное поведение . Это может дать разные результаты уже при следующем выполнении на той же машине.

Напротив, Java, похоже, определяет это поведение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...