Скомпилируйте и выполните этот код в 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
Еще одна вещь, если мы применяем префикс ++
оператор, мы получаем тот же результат на обоих языках, почему?
Это потому, что a[index++] = индекс = индекс + 2;
вызывает Неопределенное поведение в C.
Взгляните на this
From the link:
...во втором предложении сказано: если объект записывается в пределах полного выражения, то любой и все обращения к нему в пределах одного и того же выражения должны быть непосредственно вовлечены в вычисление записываемого значения. Это правило фактически ограничивает юридические выражения теми, в которых доступ к ним явно предшествует модификации. Например, разрешен старый режим ожидания i = i + 1, поскольку доступ i используется для определения конечного значения i. Пример
a[i] = i++
запрещено, так как один из обращений к i (, который находится в a[i]) не имеет никакого отношения к значению, которое в итоге хранится в i (что происходит в i++), и поэтому нет хорошего способа определить - ни для нашего понимания, ни для компилятора - должен ли этот доступ иметь место до или после хранения инкрементированного значения. Так как нет хорошего способа определить его, Стандарт заявляет, что он неопределен и что переносимые программы просто не должны использовать такие конструкции. Аналогично
a[i++]=i
(который вызывает UB) ваше выражение тоже вызывает UB.
Ваше выражение также имеет аналогичное поведение.
Поведение хорошо определено в Java
.