Неопределенное поведение в данном коде?

Каково возвращаемое значение f (p, p), если значение p
инициализировать до 5 до звонка? Обратите внимание, что первый параметр
передается по ссылке, тогда как второй параметр передается по значению.

int f (int &x, int c) {
c = c - 1;
if (c==0) return 1;
x = x + 1;
return f(x,c) * x;
}

Варианты:

  1. 3024
  2. 6561
  3. 55440
  4. 161051

Я пытаюсь объяснить:


В этом коде будет четыре рекурсивных вызова с параметрами (6,4), (7,3), (8,2) и (9,1). Последний вызов возвращает 1. Но из-за передачи по ссылке x во всех предыдущих функциях теперь равен 9. Следовательно, значение, возвращаемое f (p, p), будет 9 * 9 * 9 * 9 * 1 = 6561.


Этот вопрос из конкурсного экзамена GATE, (см. Q.no.-42). Ключ ответа задается GATE «Marks to all» (означает, что нет правильной опции). набор ключей-C, № Q-42. Где-то объясняется как:

В GATE 2013 всем были даны метки, так как один и тот же код на C / C ++ вызывает неопределенное поведение. Это потому что * не является точкой последовательности в C / C ++. Правильный код должен заменить

return f(x,c) * x;

с

 res = f(x,c);
return res * x;

Но данный код работает нормально. Ключ GATE неверен? Или это действительно ошибка с вопросом?

5

Решение

   return f(x,c) * x;

Результат этой операции зависит от порядка, в котором оцениваются две вещи. Поскольку вы не можете предсказать порядок их оценки, вы не можете предсказать результат этой операции.

14

Другие решения

C ++ 03 глава 5:

Если не указано иное, порядок вычисления операндов отдельных операторов и подвыражений отдельных
выражения и порядок возникновения побочных эффектов не определены.

Так что в случае f(x,c) * xпорядок вычисления операндов не определен, а это означает, что вы не можете знать, будет ли вычисляться первый или правый операнд первым.

Ваш код имеет неуточненное поведение, Это означает, что он будет вести себя определенным образом, который известен только компилятору. Программист не может знать, что будет делать код, только то, что он будет сначала вычислять левый операнд или сначала правый операнд. Компилятору даже разрешено изменять порядок оценки в каждом конкретном случае, в целях оптимизации.

Если порядок оценки имеет значение, вам нужно переписать код. Код, основанный на неопределенном поведении, всегда является ошибкой, возможно, довольно тонкой, которая не сразу появится.

Неопределенное поведение отличается от неопределенного поведения, что может означать, что может произойти все что угодно, включая сбой или сбой программы.

9

По вопросам рекламы [email protected]