Ответ 1
Вы правы, стандарт C (99) ничего не говорит о преобразовании из указателя в функцию в pointer-to-object, поэтому он undefined. *
* Обратите внимание, однако, что он определяет поведение между типами указателя на функцию.
Я не прав о следующем?
Стандарты на С++ говорят, что преобразование между указателем на функцию и указателем на объект (и обратно) условно поддерживается семантикой, определяемой реализацией, в то время как все стандарты C говорят, что это запрещено во всех случаях, правильно? /p >
void foo() {}
int main(void)
{
void (*fp)() = foo;
void* ptr = (void*)fp;
return 0;
}
ISO/IEC 14882: 2011
5.2.10 Реинтерпретировать литье [expr.reinterpret.cast]
8 Преобразование указателя функции в тип указателя объекта или наоборот versa условно поддерживается. Значение такого преобразования определяется реализацией, за исключением того, что если реализация поддерживает преобразования в обоих направлениях, преобразование значения одного типа в другой тип и обратно, возможно с различной cvqualification, должен дать исходное значение указателя.
Я не могу найти ничего об этом в стандарте C прямо сейчас...
Вы правы, стандарт C (99) ничего не говорит о преобразовании из указателя в функцию в pointer-to-object, поэтому он undefined. *
J.5.7 Функции указателей функций
Указатель на объект или на void может быть передан указателю на функцию, что позволяет использовать данные в качестве функции (6.5.4).
Указатель на функцию может быть перенесен на указатель на объект или на void, позволяя проверять или изменять функцию (например, отладчиком) (6.5.4).
Во всех стандартах C преобразование между указателем на функцию и указателем на объект не определено, в С++ до С++ 11 преобразование не было разрешено, и компиляторы должны были дать ошибку, но были компиляторы который принял преобразование для C и обратную совместимость и потому что он полезен для таких вещей, как доступ к динамически загружаемым библиотекам (например, функция dlsym
POSIX требует его использования). В С++ 11 было введено понятие условно-поддерживаемых функций, которое использовалось для адаптации стандарта с существующей практикой. Теперь либо компилятор должен отклонить программу, пытающуюся сделать такое преобразование, либо должен соблюдать ограниченные ограничения.
Хотя поведение приведения не определяется "ядром" стандарта, этот случай явно описывается как недопустимый в документе обоснования C99 (6.3.2.3, Указатели):
Ничего не сказано о указателях на функции, которые могут быть несоизмеримы с указателями объектов и/или целыми числами.
Даже при явном приведении недопустимо преобразовывать указатель на указатель на объект или указатель на void или наоборот.
И так как это может быть полезно, оно также упоминается в Приложении J стандарта как "общее расширение" (C11 Standard J.5.7, Casting).
Указатель на объект или
void
может быть добавлен к указателю на функцию, что позволяет использовать данные в качестве функции (6.5.4).Указатель на функцию может быть перенесен на указатель на объект или на
void
, что позволяет функции, которая должна быть проверена или изменена (например, отладчиком) (6.5.4).
Описывая это как расширение, это означает, что это не является частью стандартных требований (но это не было необходимо, упущения любого явного поведения достаточно).