Как 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");
Как это все еще работает каждый раз?
Ответы
Ответ 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 использует регистры для первых четырех невариантных аргументов.
Это не меняет того факта, что ваш код ошибочен, и вам нужно исправить его, если вы хотите получить правильный ответ последовательно.