Причина, по которой этот код компилируется, а func[4]
не является синтаксической ошибкой:
1. Типы функций могут неявно преобразовываться в указатели одного типа.Итак, если у нас есть код, подобный этому:
int f(int);
using func_t = int(*)(int);
void g(func_t);
, мы можем написать
g(f)
и не должны писать g(&f)
.&
, переводящий нас из типа int(int)
в int(*)(int)
, происходит неявно.
2.В C (и обязательно в C ++ для совместимости) указатели подключаются к массивам, а когда p
являетсяуказатель p[x]
совпадает с *(p + x)
.Так что func[4]
- это то же самое, что и *(func + 4)
.
3. *(p+x)
имеет тип функции int(int)
, но, опять же, может неявно переходить в тип указателя при необходимости.Так что *(func + 4)
неявно может быть просто (func + 4)
.
4. Указатели любого типа могут быть устойчивы к std::cout
.
Обратите внимание, что только потому, что это несинтаксическая ошибка не означает, что она действительна.Конечно, это неопределенное поведение, и, как указывает предупреждение компилятора, генерируемое gcc и clang, арифметика указателя с указателем на функцию, как правило, неверна, поскольку вы не можете создать массив функций.Реализация размещает функции как угодно.(Вы можете создать массив указателей на функции, но это совсем другое.)
Редактировать: Я должен исправить себя - этот ответ не совсем корректен.func[4]
недопустимо, поскольку указатель не является указателем на тип объекта.@holyblackcat ответ правильный, см. его ответ для справки в стандарте.
Этот код должен быть некорректным, и gcc только компилирует его без ошибок, поскольку по умолчанию они используют нестандартное расширение.Clang и msvc корректно отклоняют этот код.