2015-09-30 16 views
5

Каково возвращаемое значение 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; 
} 

Варианты:


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


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


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

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

return f(x,c) * x; 

с

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

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

+2

Одна из вещей, которые могут произойти, если вы пересечете улицу, не глядя в обоих направлениях, - это безопасное перемещение на другую сторону. Но это ошибка * предсказать *, что человек, который пересекает улицу, не глядя в обоих направлениях, будет безопасно перемещаться на другую сторону. –

+0

Как [неопределенность по поведению Sequence Point, неопределенное поведение?] (Http://stackoverflow.com/q/29513572/1708801) –

ответ

14
return f(x,c) * x; 

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

+0

сэр, почему здесь отлично работает [этот код] (http://cpp.sh/8m6y) –

+5

@ user4791206 Что значит «отлично работает»? Поскольку вы не можете предсказать, что он будет делать, почему бы вам сказать, что это произошло, это нормально работать? Кто-то, кто предсказал это, оценил бы в другом порядке, не сказал бы, что это сработало хорошо, не так ли? –

+0

Значения, проблема порядка оценки - это неопределенное поведение [I-read] (http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points)? –

9

C++ 03 Глава 5:

За исключением особо оговоренных случаев, порядок оценки операндами отдельных операторов и подвыражениям отдельных выражений, а также порядок, в котором побочные эффекты имеют место, не определено.

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

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

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

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

+2

В качестве примечания стороны тот же текст отличается от C++ 11, но имеет тот же смысл. Я думаю, что C++ 11 (и C11) заставил текст гораздо сложнее понять, почему я цитирую более старую версию стандарта. – Lundin

+0

Спасибо, сэр, я понял. –

+0

В целом «неуказанное поведение» не означает, что программист не может знать, что будет делать код - просто, что программист не может знать в каком-либо конкретном случае, какое из возможных вариантов поведения выберет компилятор. Если все возможные комбинации поведения компилятора отвечают требованиям программиста, тогда программист будет иметь право ожидать, что программа будет работать правильно. Нет ничего плохого в том, что код, основанный на выборе компилятором неуказанным способом из определенных действий, пока он будет работать с любым таким выбором, который делает компилятор. – supercat