вызов функции c ++ с квадратными скобками - PullRequest
0 голосов
/ 08 октября 2018
int func(int n)
{return n;}

int main()
{ cout << func[4] ;
cout << func[4,3,5] ;}

что это на самом деле означает?Я предполагаю, что речь идет о доступе к func + 4, и func выделяет место для вызова func [4].Но func [4,3,5] просто абсурден.

Ответы [ 4 ]

0 голосов
/ 09 октября 2018

Я удивлен, что ни один ответ не упоминает об этом, но:

Код в вопросе просто недействителен C ++.

Это отклонено Clang и MSVC без флагов.GCC отклоняет это с -pedantic-errors.

a[b] (при отсутствии перегрузки оператора) определяется как *(a + b), а встроенный оператор + требует, чтобы операндом указателя был указатель на тип объекта (которыйуказатели на функции не являются).

[expr.add] / 1

... либо оба операнда должны иметь арифметический или незавершенный тип перечисления, либо один операнд должен быть указателем на полностью определенный тип объекта , а другой должен иметь целочисленный или незаданный тип перечисления.

(выделение.)


GCC компилирует код, потому что расширение, разрешающее арифметику для указателя функции , включено по умолчанию.

Из-за затухания функции в указатель func[4] рассматривается как &(&func)[4],что фактически означает &func + 4, что (как объясняет ссылка) просто добавляет 4 к числовому значению указателя.Вызов результирующего указателя, скорее всего, вызовет сбой или непредсказуемые результаты.

std::cout не имеет перегрузки <<, подходящей для печати указателей на функции, и наилучшая подходящая перегрузка, которую компилятор может найти, - этоодин для печати bool с.Указатель преобразуется в bool, и, поскольку он не равен нулю, он становится true, который затем печатается как 1.

Наконец, func[4,3,5] имеет тот же эффект, что и func[5]поскольку в этом контексте , рассматривается как оператор, а x , y равен y.

0 голосов
/ 08 октября 2018

Причина, по которой этот код компилируется, а 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 корректно отклоняют этот код.

0 голосов
/ 08 октября 2018

Поскольку это еще не было упомянуто: func[3, 4, 5] идентичен func[5] - запятые в нем - встроенный оператор запятой , который вычисляет выражение левой стороны, отбрасывает его и затем вычисляетвыражение правой стороны.Здесь нет вызова функции, и запятые в коде не разделяют параметры функции.

0 голосов
/ 08 октября 2018

Да, речь идет о доступе к func + 4, который еще не определен, что приводит к значению мусора. Поэтому компилятор укажет вам следующее предупреждающее сообщение.

hereProgram: In function 'int main()':
Program:7: warning: pointer to a function used in arithmetic
...