#c #casting #function-pointers
#c #Кастинг #указатели на функции
Вопрос:
Насколько я знаю, приведение между несовместимыми указателями на функции, например:
void aUnaryFunction(int a1)
{
/* .... */
}
void doSomethingWithFn()
{
typedef void(*BinaryFn)(int, const char*);
BinaryFn aBinaryFunction = (BinaryFn) amp;aUnaryFunction;
aBinaryFunction (3, "!!!");
}
никогда не должно быть сделано, как и «неопределенное поведение» в соответствии со стандартом C.
Однако я не могу понять, почему, учитывая способ работы вызовов функций в C, этот пример небезопасен. Все, что я делаю, это игнорирую аргумент.
Предполагая, что обработка первого аргумента int является согласованной, все, что произойдет, это то, что const char * будет помещен в регистр при doSomethingWithFn()
вызовах aBinaryFunction
, aUnaryFunction
будет выполняться как ожидалось, и const char * может быть перезаписан во время aUnaryFunction
, но это нормально, потому что ничто другое все равно не будет его использовать.
Я что-то здесь упускаю, или это на самом деле безопасно? (Или что-то среднее между ними, или оба?)
Ответ №1:
Проблема в том, что не существует единого «способа, которым вызовы функций работают в C» — есть только способ, которым вызовы функций работают в конкретной реализации C.
В качестве конкретного примера, соглашения о вызовах «очистка вызываемого объекта» (например, x86 stdcall
) требуют, чтобы вызываемый объект знал, сколько параметров было добавлено в стек для выполнения правильной очистки, которая была бы нарушена в вашем примере.
Ответ №2:
Это сводится к соглашениям о вызовах. Что, если аргументы «отправляются», например, в обратном порядке? Или если есть стандартная процедура, которая должна быть выполнена после вызова функции, которая полагается на нужное количество аргументов?
То, что вы предлагаете, может сработать, но вы не должны полагаться на это, и Стандарт по какой-то причине приписывает это неопределенному поведению.
Ответ №3:
Кстати, ‘неопределенное поведение’ — это секретный код для «не делай этого, это небезопасно!».
Это указывает на то, что это не будет работать на разных машинах или даже на разных версиях одного и того же компилятора на одной машине.