Подтвердить что ты не робот

Как printf() "загадочно" знает, что я намеревался напечатать?

Я забыл добавить сопровождающие переменные к вызову printf(). Как printf() знает, что я хочу напечатать?

int successful = 0;//Flag
printf("\nEnter a number to search for: ");
scanf("%d", &data);
successful = search(list, data);
successful? printf("\n'%d' was found\n\n", data) : printf("\n'%d' was NOT found\n\n");

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

: printf("\n'%d' was NOT found\n\n");

Как это все еще работает каждый раз?

4b9b3361

Ответ 1

Возможно, он работает, но НЕ СООТВЕТСТВУЕТ ЭТО.

Вероятно, это работает, потому что ваш последний вызов функции,

successful = search(list, data);

оставил значение data в соответствующем месте в стеке.


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

int wowee () {
    int val;
    val = 12;

    // <-- no return statement!
}

Иногда локальная переменная val будет возвращена, вероятно, из-за повторного использования такого же типа стека. Но это также поведение undefined, даже если оно работает.


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

Ответ 2

Упс! Это "Undefined Поведение".

printf("\n'%d' was NOT found\n\n"); // undefined behavior

"Undefined Поведение" - это технический термин, который в основном означает... что-то может случиться. Возможно, правильная вещь может произойти, может быть, программа потерпит крах, или, может быть, она сделает что-то еще полностью.

В этом случае, возможно, значение, которое вы хотите, уже находится в стеке в нужном месте, поэтому, когда printf(), когда нужно взять его аргумент, он получил правильное значение. Это сильно зависит от использования оптимизации и конкретного ABI, который вы используете, в частности, не все ABI помещают значения в стек для невариантных вызовов функций.

successful = search(list, data);
//                        ^^^^ places "data" on stack as second argument

Если вы скомпилируете свою программу как 64-разрядную, она больше не будет работать, так как наиболее распространенный x64 ABI использует регистры для первых четырех невариантных аргументов.

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