Логические различия в C и Java - PullRequest
35 голосов
/ 08 января 2010

Скомпилируйте и запустите этот код на C

#include <stdio.h>

int main()
{
  int a[] = {10, 20, 30, 40, 50};
  int index = 2;
  int i;

  a[index++] = index = index + 2;
  for(i = 0; i <= 4; i++)
    printf("%d\n", a[i]);
}

Выход: 10 20 4 40 50

Теперь для той же логики в Java

class Check
{

  public static void main(String[] ar)
  {
    int a[] = {10, 20, 30, 40, 50};
    int index = 2;

    a[index++] = index = index + 2;
    for(int i = 0; i <= 4; i++)
      System.out.println(a[i]);
  }
}

Выход: 10 20 5 40 50

Почему на обоих языках разница в выводе, вывод понятен для Java, но я не могу понять вывод в C

Еще одна вещь, если мы применяем префиксный оператор ++, мы получаем одинаковый результат на обоих языках, почему?

1 Ответ

64 голосов
/ 08 января 2010

Это потому, что a[index++] = index = index + 2; вызывает неопределенное поведение в C. Посмотрите на это

Из ссылки:

.. второе предложение гласит: если объект записан в пределах полного выражения, любой и все обращения к нему в пределах одного и того же выражения должны быть непосредственно вовлечены в вычисление значения, которое должно быть записано. Это правило эффективно ограничивает юридические выражения теми, в которых доступы явно предшествуют модификации. Например, старый резервный i = i + 1 разрешен, потому что доступ i используется для определения окончательного значения i. Пример

 a[i] = i++

запрещено, потому что один из обращений к i ( тот, что в [i]) не имеет ничего общего со значением, которое в итоге сохраняется в i (что происходит в i ++), и поэтому нет хорошего способа определить - для нашего понимания или для компилятора - должен ли доступ осуществляться до или после сохранения увеличенного значения . Поскольку нет хорошего способа определить его, Стандарт заявляет, что он не определен, и что переносимые программы просто не должны использовать такие конструкции. Подобно a[i++]=i (который вызывает UB), ваше выражение также вызывает UB.

Ваше выражение также имеет похожее поведение.

Поведение четко определено в Java.

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