Почему всегда ответ равен 5? - PullRequest
0 голосов
/ 26 февраля 2019

Предоставление этого кода:

#include <iostream>
#include <cmath>
using namespace std;

int main() {
    int k, x;

    while(k > x-3) {
         k--;
         // cout << "x = " << x << "\n";
    }
    x++, k--;

    int aux = abs(k-x);
    cout << aux;
}

Когда мы его запускаем, всегда всплывает константа x (x = 50), а абсолютное значение между целым числом k и x всегда равно 5. Можете ли выобъясните пожалуйста, почему и как это работает?

Ответы [ 3 ]

0 голосов
/ 26 февраля 2019

Матье и πάντα ῥεῖ верны: это классическое неопределенное поведение.(Одно обоснование для того, чтобы сделать его неопределенным , а не просто неопределенным или реализацией, определенной , заключается в том, что некоторые архитектуры имеют флаги для неинициализированных регистров и могут перехватывать.) Фактически, компиляторможно скомпилировать ее в пустую программу: чтение неинициализированной переменной может привести к что угодно - и ничто является подмножеством что угодно .Весь последующий код после неопределенного поведения «испорчен» предыдущей ошибкой и может быть опущен.Обратите внимание, что разные архитектуры и разные компиляторы, возможно, даже разные стандартные библиотеки C (с одним и тем же компилятором!) Могут давать разные результаты;даже другой флаг компилятора (касающийся соглашений об оптимизации или вызове функций) может изменить это неопределенное поведение.

( Остальная часть этого ответа относится к версии вопроса, где строкапосле цикла прочитайте x++, k++; (вместо k-- как сейчас). )

Но вы столкнулись с непротиворечивым поведением, и вопрос в том, почему оно непротиворечивое.Первое предположение состоит в том, что компилятор не просто генерирует код для вывода «5» (что он мог, законно), но фактически «наивно» генерирует машинный код, который соответствует операторам C.Мы рассмотрим приведенные ниже утверждения.

Затем поведение указывает, что области памяти, в которых находятся x и k, содержат значения, из-за которых k > x -3 сразу ложно.(В противном случае k будет уменьшаться до тех пор, пока разница не станет 3, а не 5).

Если условие ложно, разница в переменной не изменится;из этого можно сделать вывод, что это было 5 с самого начала с x-k == 5.Если вы опустите abs(), выходное значение должно быть -5.

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

0 голосов
/ 26 февраля 2019

Я действительно думаю, что вы должны попробовать два произвольных числа.Например, представьте, что мы используем k= 10 & x=8.Ваш цикл будет выглядеть так: While(10>5) 10-1=9 ... и так далее, пока K не станет больше, чем (X-3).Вы получите k = 5, а x это то же значение, 8.После цикла while вы уменьшаете k и увеличиваете x, поэтому k = 4 и x = 9.Abs(k-x) = 5.

Если вам нужно более теоретическое объяснение, цикл предоставит разность между вашими двумя переменными равной 3, X будет больше, чем K. Как после цикла, вы уменьшаете K и увеличиваете Xразница между ними ВСЕГДА будет 5.

0 голосов
/ 26 февраля 2019

С ограничением "k больше x" этот фрагмент кода здесь

while(k > x-3) {
     k--;
     // cout << "x = " << x << "\n";
}

уменьшится k до 3 меньше x.

Следующая строка, x++, k++; увеличивает их обоих на 1, но это не меняет результат.k по-прежнему 3 меньше, чем x.

k-x равно -3, а abs(k-x) равно 3, поэтому программа всегда печатает 3.Предполагая, конечно, что k и x инициализированы и что k больше x.Программа в том виде, в каком она опубликована с неинициализированными k и x, демонстрирует неопределенное поведение, поэтому нет гарантии того, что произойдет.Кроме того, как указывает Аконкагуа, если x меньше INT_MIN + 3, это также ведет к неопределенному поведению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...