Информация об изменениях

Сообщение Re[4]: char *(*(**foo[][8])())[]; - за сколько распарсите? от 07.05.2023 10:48

Изменено 07.05.2023 11:03 rg45

Re[4]: char *(*(**foo[][8])())[]; - за сколько распарсите?
Здравствуйте, Shmj, Вы писали:

S>В С++ много неочевидных моментов, связанных с декларированием сложных вещей. К примеру, пока не увидел какая сигнатура у функции, возвращающей указатель на другую функцию — никогда бы сам не догадался.


На самом деле, ничего особенно сложного нет, нужно знать лишь пару несложных принципов. Первое, что нужно знать — результатом функции не может быть другая функция или массив, но результатом может быть указатель на функцию или массив. Второе, что нужно знать — для того, чтобы объявить указатель на функцию или массив, нужно использовать дополнительные круглые скобки, которыми мы как-бы присоединим символ указателя к имени массива или функции. Без этих дополнтительных круглых скобок символ указателя будет относиться либо к результату функции, либо к элементу массива.

Конструирование сложного типа осуществляется добавлением новых синтаксических элементов К ИМЕНИ декларации. Например, имеем изначально простое объявление:

Функция, принимающая строку и возвращающая число:
int foo(const char*);


Указатель на функцию, принимающую строку и возвращающую число (используем дополнительные круглые скобки):
int (*foo)(const char*);


Массив указателей на функции принимающие строку, и возвращающие число
int (*foo[42])(const char*);


Указатель на массив указателей на функции принимающие строку, и возвращающие число (опять используем дополнительные круглые скобки)
int (*(*foo)[42])(const char*);


Функция, принимающая double, возвращающая указатель на массив указателей на функции принимающие строку, и возвращающие число
(просто добавляем справа от имени декларации список формальных параметров в круглых скобках):
int (*(*foo(double))[42])(const char*);


Указатель на функцию, принимающую double, возвращающую указатель на массив указателей на функции принимающие строку, и возвращающие число
int (*(*(*foo)(double))[42])(const char*);


Анализ выполняется в обратном порядке, начиная от имени объявления.

Сложнее всего, когда имя в объявлении опущено и найти его не всегда просто:
using FooPtr = int (*(*(*)(double))[42])(const char*);

Тут уже нужно иметь некоторую сноровку, чтобы быстро находить точку отсчета, от которой следует проводить разбор.

Но на практике таких многоэтажных объявлений лучше вообще избегать, используя using или typedef.
Re[4]: char *(*(**foo[][8])())[]; - за сколько распарсите?
Здравствуйте, Shmj, Вы писали:

S>В С++ много неочевидных моментов, связанных с декларированием сложных вещей. К примеру, пока не увидел какая сигнатура у функции, возвращающей указатель на другую функцию — никогда бы сам не догадался.


На самом деле, ничего особенно сложного нет, нужно знать лишь пару несложных принципов. Первое, что нужно знать — результатом функции не может быть другая функция или массив, но результатом может быть указатель на функцию или массив. Второе, что нужно знать — для того, чтобы объявить указатель на функцию или массив, нужно использовать дополнительные круглые скобки, которыми мы как-бы присоединим символ указателя к имени массива или функции. Без этих дополнтительных круглых скобок символ указателя будет относиться либо к результату функции, либо к элементу массива.

Конструирование сложного типа осуществляется добавлением новых синтаксических элементов К ИМЕНИ декларации. Например, имеем изначально простое объявление:

Функция, принимающая строку и возвращающая число:
int foo(const char*);


Указатель на функцию, принимающую строку и возвращающую число (используем дополнительные круглые скобки):
int (*foo)(const char*);


Массив указателей на функции принимающие строку, и возвращающие число (добавляем квадратные скобки с размерностью массива сразу справа от имени):
int (*foo[42])(const char*);


Указатель на массив указателей на функции принимающие строку, и возвращающие число (опять используем дополнительные круглые скобки)
int (*(*foo)[42])(const char*);


Функция, принимающая double, возвращающая указатель на массив указателей на функции принимающие строку, и возвращающие число
(просто добавляем справа от имени декларации список формальных параметров в круглых скобках):
int (*(*foo(double))[42])(const char*);


Указатель на функцию, принимающую double, возвращающую указатель на массив указателей на функции принимающие строку, и возвращающие число
int (*(*(*foo)(double))[42])(const char*);


Анализ выполняется в обратном порядке, начиная от имени объявления.

Сложнее всего, когда имя в объявлении опущено и найти его не всегда просто:
using FooPtr = int (*(*(*)(double))[42])(const char*);

Тут уже нужно иметь некоторую сноровку, чтобы быстро находить точку отсчета, от которой следует проводить разбор.

Но на практике таких многоэтажных объявлений лучше вообще избегать, используя using или typedef.