Я недавно ночью писал код и допустил ошибку. Мне нужно было записать в виртуальную память процесса указатель на нужную функцию. Делал я это так:
uint64_t *some_mapped_memory = ...;
some_mapped_memory[0] = reinterpret_cast<uint64_t>(myFunc);
Ошибка в том, что я не поставил & перед именем функции. И кастанулся не указатель, а "сама функция". Однако этот код работал так же, как и ожидалось.
Более того, позже я произвел тест:
#include <cstdio>
void f() {}
int main() {
void (*fnc1)() = f;
void (*fnc2)() = &f;
printf("%p %p\n", f, &f);
return 0;
}
Мало того, что printf вывел два одинаковые значения, так еще и код выше скомпилировался без проблем.
Я немного погуглил, но ничего не нашел по этому поводу. Честно говоря, нет под рукой gcc или вообще другого компилятора, тестировал с visual c++. Что по поводу моего кода думает стандарт? Ну обязано ли это работать на другом компиляторе, или валидным является только &f? И почему моя среда разработки показывает, что fnc1 и fnc2 оба являются void(*)(), однако auto fnc3 = f является void()?
В общем, то, что я показал - это какое-то злое умное преобразование, описанное стандартом, или же злое умное преобразование, которое может visual c++?
Имя функции (не функции-члена!) всегда может быть преобразовано в указатель на функцию, вне зависимости от наличия амперсанда перед именем функции. Черновик C++17 [conv.func]:
An lvalue of function type T can be converted to a prvalue of type “pointer to T”. The result is a pointer to the function.
Чуть больше про указатели на функции можно найти в моей статье, хотя там нет ссылок на стандарт, т.к. рассчитана она на начальный уровень.
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости