Подтвердить что ты не робот

Логические различия в C и Java

Скомпилируйте и запустите этот код в 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

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

4b9b3361

Ответ 1

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

Из ссылки:

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

 a[i] = i++

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

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

Поведение хорошо определено в Java.