стр.77 K & R C говорит, что выход следующей программы не определен, но текущая версия Xcode не дает никаких предупреждений. Все еще не определено в текущем стандарте? Как насчет C++? Бонусные очки для аналогичной программы на Java и С#.
#include <stdio.h>
int my_m()
{
static int n = 0;
static int m[] = { 42, 57 };
return n++ % 2 == 0 ? m[0] : m[1];
}
int main()
{
printf("%d" , my_m() - my_m());
return 0;
}
Результат на самом деле не определен, просто не указан.
Разница в том, что неопределенное поведение означает, что все может случиться, в том числе поведение, которое, по-видимому, полностью не связано ни с чем в программе. Классическая линия заключается в том, что она "заставляет демонов вылететь из вашего носа".
Произвольные означает, что вы не имеете никакого способа знать, какой вызов my_m
будет оцениваться первым и который будет оцениваться вторым, но это будет 1 один вызовом, а затем другие. Один вызов начнется и запустится до завершения, тогда другой вызов начнется и запустится до завершения - два не будут чередоваться или что-то в этом роде. Единственное, что непредсказуемо, это порядок, в котором совершаются два вызова (и да, в соответствии со стандартами C и C++, заказ все еще на 100% непредсказуем).
Как в С#, так и в Java порядок оценки указан как слева направо.
1. Или, по крайней мере, он будет действовать так, как если бы это было так.И C, и C++ следуют тому, что обычно называется "как если бы", что позволяет компилятору делать что-то по-другому, если это так, что поддерживает указанное внешне видимое поведение.
Компилятор не будет предупреждать вас обо всех неопределенных программах. В следующей строке:
printf("%d" , my_m() - my_m());
порядок вызовов my_m()
не my_m()
. Компилятор может решить сначала вызвать либо первый, либо второй. Поскольку функция возвращает 42
при первом вызове, а 57
во втором вызове, результат равен 42 - 57
или 57 - 42
.
Изменение: я пропустил разницу между неопределенным и неуказанным, см. Ответ Джерри Коффинса для получения подробностей об этом.