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

Отправляет между указателем на функцию и указателем на объект в C и С++

Я не прав о следующем?

Стандарты на С++ говорят, что преобразование между указателем на функцию и указателем на объект (и обратно) условно поддерживается семантикой, определяемой реализацией, в то время как все стандарты 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 прямо сейчас...

4b9b3361

Ответ 1

Вы правы, стандарт C (99) ничего не говорит о преобразовании из указателя в функцию в pointer-to-object, поэтому он undefined. *


* Обратите внимание, однако, что он определяет поведение между типами указателя на функцию.

Ответ 2

  • В С++ 03 такие преобразования были незаконными (а не UB). Компилятор должен был выпустить диагностику. Многие компиляторы в Unix-системах не выдавали диагностику. Это было по существу столкновение между стандартами, POSIX vs С++.
  • В С++ 11 такие преобразования "условно поддерживаются". Диагностика не требуется, если система поддерживает такие преобразования; там ничего не диагностировать.
  • В C такие преобразования официально являются undefined, поэтому никакой диагностики не требуется. Если система выполняет "правильную" вещь, хорошо, что один из способов реализации UB.
  • В C99 это снова UB. Однако в стандарте также перечислены такие преобразования, как одно из "общих расширений" для языка:

    J.5.7 Функции указателей функций
    Указатель на объект или на void может быть передан указателю на функцию, что позволяет использовать данные в качестве функции (6.5.4).
    Указатель на функцию может быть перенесен на указатель на объект или на void, позволяя проверять или изменять функцию (например, отладчиком) (6.5.4).

Ответ 3

Во всех стандартах C преобразование между указателем на функцию и указателем на объект не определено, в С++ до С++ 11 преобразование не было разрешено, и компиляторы должны были дать ошибку, но были компиляторы который принял преобразование для C и обратную совместимость и потому что он полезен для таких вещей, как доступ к динамически загружаемым библиотекам (например, функция dlsym POSIX требует его использования). В С++ 11 было введено понятие условно-поддерживаемых функций, которое использовалось для адаптации стандарта с существующей практикой. Теперь либо компилятор должен отклонить программу, пытающуюся сделать такое преобразование, либо должен соблюдать ограниченные ограничения.

Ответ 4

Хотя поведение приведения не определяется "ядром" стандарта, этот случай явно описывается как недопустимый в документе обоснования C99 (6.3.2.3, Указатели):

Ничего не сказано о указателях на функции, которые могут быть несоизмеримы с указателями объектов и/или целыми числами.

Даже при явном приведении недопустимо преобразовывать указатель на указатель на объект или указатель на void или наоборот.

И так как это может быть полезно, оно также упоминается в Приложении J стандарта как "общее расширение" (C11 Standard J.5.7, Casting).

Указатель на объект или void может быть добавлен к указателю на функцию, что позволяет использовать данные в качестве функции (6.5.4).

Указатель на функцию может быть перенесен на указатель на объект или на void, что позволяет функции, которая должна быть проверена или изменена (например, отладчиком) (6.5.4).

Описывая это как расширение, это означает, что это не является частью стандартных требований (но это не было необходимо, упущения любого явного поведения достаточно).