Что означает typedef A (*AF)()?

Недавно был открыт мой основной язык программирования, j. источник. Чтобы улучшить его, я изучаю исходники, которые написаны на C.

Но прошло много времени (!) с тех пор, как я читал или писал C, и тогда я даже не был хорош в этом. И то, как написана эта конкретная кодовая база, является ... идиосинкразическим (многие интерпретаторы APL, в том числе J, имеют свой исходный код, написанный в высокоуровневом «стиле APL», даже если он написан на низкоуровневом языке; очень краткий, избыточность избегается , интенсивное использование макросов и т. д.)

На данный момент я пытаюсь понять основные структуры данных, которые он использует. Наиболее фундаментальным из них является typedef A ("A" для "массив"):

typedef struct {I k,flag,m,t,c,n,r,s[1];}* A;

что я прекрасно понимаю. Но я изо всех сил пытаюсь понять, что такое AF двумя строками позже:

typedef A (*AF)();

Что означает этот синтаксис? В частности, что это означает, когда вещи позже объявляются как «тип AF»? Является ли AF просто указателем на A?

Моей непосредственной целью является интерпретация дампов памяти, которые включают элементы типа V (для "verb"), первыми двумя членами которого являются AFs:

typedef struct {AF f1,f2;A f,g,h;I flag,mr,lr,rr,fdep;C id;} V;

но моя общая цель шире, поэтому, пожалуйста, уточните синтаксис, используемый в определении AF.


c j
person Dan Bron    schedule 11.08.2015    source источник
comment
AF — это указатель на функцию, которая не принимает параметров и возвращает A.   -  person Sergey Kalinichenko    schedule 11.08.2015
comment
@dasblinkenlight: это верно для C++. В C это typedef для функции с неопределенным, но фиксированным числом и типом (типами) параметров и возвращает A. Скорее всего, его следует определить как typedef A (*AF)(void);. Если он действительно предназначен для приема произвольного количества аргументов, то вы можете очень легко получить неопределенное поведение, вызвав функцию неправильно, без диагностики компилятора.   -  person Keith Thompson    schedule 11.08.2015
comment
Эта кодовая база ужасна. Ты должен бежать с криком.   -  person Hogan    schedule 11.08.2015
comment
@KeithThompson Стоит отметить, что в J функции могут принимать либо один аргумент (оба типа A), либо два аргумента (типа A) и всегда возвращать A. Не существует такой вещи, как функция с нулем или более чем двумя аргументами, или функция, которая принимает аргументы любого типа, кроме типа A. Так что мне странно, что вы говорите, что AF может принимать фиксированное количество аргументов: мне кажется, что она должна иметь возможность принимать один или два.   -  person Dan Bron    schedule 11.08.2015
comment
В в C нет способа указать, что функция может принимать один или два аргумента. Большинство функций принимают фиксированное количество аргументов, определяемое при объявлении/определении функции; это число может быть от 0 до любого абсурдно большого числа, поддерживаемого компилятором. Функция, объявленная с помощью (), принимает фиксированное, но не указанное количество аргументов. Соответствующее определение определяет фактическое количество и тип(ы) параметров. Это устаревшая функция. Функция variadic, например printf, объявляется/определяется с помощью , ... и принимает N фиксированных аргументов плюс 0 или более...   -  person Keith Thompson    schedule 11.08.2015
comment
... дополнительные аргументы. В C++ вы можете перегрузить функцию, поэтому есть две версии: A func(A) и A func(A, A); это будут две разные функции, которые имеют одно и то же имя. C не поддерживает перегрузку, но вы можете определить A func1(A) и A func2(A, A). (Я не знаю J, поэтому не могу комментировать, как это работает.)   -  person Keith Thompson    schedule 11.08.2015
comment
Это означает, что вы используете неправильный язык!   -  person Dov    schedule 11.08.2015
comment
Краткость J, по-видимому, повлияла на реализацию с ужасными результатами.   -  person Paul Draper    schedule 11.08.2015
comment
В качестве примера, когда исправление того, что некоторые люди называют ужасным, может привести к чему-то гораздо худшему, рассмотрим FARPROC, который является указателем на функцию в динамически подключаемой библиотеке (где количество и типы аргументов указываются в качестве левого аргумента для cd ).   -  person rdm    schedule 12.08.2015
comment
@rdm Я почти ничего не знаю о C: можете ли вы объяснить, почему исправление FARPROC ухудшит ситуацию, и почему некоторые люди могут вообще счесть FARPROC ужасным?   -  person Dan Bron    schedule 12.08.2015
comment
Некоторые люди утверждают, что аспект typedef с неуказанным количеством аргументов является устаревшей функцией C, так что это один из источников ужаса. Между тем, исправить это, вероятно, означало бы исключить возможность вызова произвольных динамически связанных функций. (Или это означало бы замену его чем-то гораздо более подробным, что, вероятно, разбило бы кеш L1).   -  person rdm    schedule 12.08.2015
comment
Для комментария ужасного: Вот вопросы и ответы от автора: Q Как обычные программисты C реагируют на это? А: С ужасом! --- Презентация Роджера Хуи перед Британской ассоциацией APL 12 февраля 1993 г.   -  person ahala    schedule 12.08.2015


Ответы (3)


Как уже было сказано, AF (Функция массива) — это указатель на функцию, которая возвращает A (указатель объекта массива).

В определении V (Глагол, т. е. функциональный объект) есть два AF. v1 — это указатель на реализацию монадической функции, а v2 — указатель на диадическую функцию. Если V представляет собой оператор (наречие), то v1 и v2 по-прежнему являются монадической и двоичной реализациями соответственно, но также f g и h могут использоваться для хранения (каррированных) левых и/или правых аргументов. mr lr и rr имеют монадический, левый и правый ранги соответственно. И id содержит код операции, так что из структуры можно восстановить печатное представление.

Если какие-либо из операндов в f g или h сами являются глаголами, их структура V будет располагаться на f->k байтах после *f соответственно для g и h, как и все "полезные данные".

Я нашел очень полезную ссылку для понимания основных типов в реализации J: заметки Роджера Хуи BAA (2,69M отсканированный pdf). Полное описание находится на странице Реализация J (html).

Вы также можете найти поучительным мой примитивный клон. См. также мои вопросы здесь и здесь.

person luser droog    schedule 11.08.2015
comment
Потрясающе, очень конкретно для моих нужд (мне было интересно узнать о f, g, h). Спасибо. Я взгляну на записи BAA и ваш клон. Цените помощь. - person Dan Bron; 11.08.2015
comment
Я принял ваш ответ, хотя он был позже, чем другие, потому что он содержит наиболее подробную информацию, относящуюся к моему проекту (стоит отметить, что я проголосовал за все опубликованные ответы). - person Dan Bron; 11.08.2015

AF — это typedef для указателя на функцию. В частности, AF относится к указателю на функцию, которая принимает неопределенное количество параметров и возвращает результат типа A.

person dbush    schedule 11.08.2015
comment
Ах, конечно. Это имеет смысл и в контексте Vs, которые являются функциями, которые обрабатывают As (и возвращают As). Спасибо. Я приму это, когда система позволит мне. - person Dan Bron; 11.08.2015
comment
Это указатель на функцию с 0 аргументами. Указатели на функции с переменным количеством аргументов используют синтаксис .... - person rlbond; 11.08.2015
comment
@rlbond Нет, функция с 0 аргументами имеет (void) в качестве списка параметров; это будет typedef A (*AF)(void). Ответ правильный: это неопределенное количество параметров. - person Filipe Gonçalves; 11.08.2015
comment
@rlbond: функции, объявленные с помощью (), сильно отличаются от функций с переменным числом переменных, объявленных с помощью , .... Первое означает, что вы все равно должны передавать аргументы, соответствующие определению, но компилятор не обнаружит ошибки (это устаревшая функция). Последнее означает, что функция может законно принимать различное количество и типы аргументов; printf — самый распространенный пример. - person Keith Thompson; 11.08.2015
comment
AF — это не указатель, а тип. Пожалуйста, постарайтесь быть точным. - person alk; 11.08.2015
comment
@alk Спасибо. Изменен указатель на указатель - person dbush; 11.08.2015

Давайте проигнорируем, что такое A на самом деле. Тогда у вас есть

typedef int (*AF)();

AF — это указатель на функцию (она же указатель на функцию), которая принимает любое количество аргументов и возвращает int. Ясно, что при замене int на A содержимое будет практически таким же, за исключением типа возвращаемого значения; поэтому окончательный результат квалифицирует AF как указатель на функцию, принимающую любое количество аргументов и возвращающую A, псевдоним указателя на анонимную структуру.

Существует интересный сайт, который может помочь преобразовать сложные объявления в удобочитаемый текст.

person edmz    schedule 11.08.2015
comment
Ницца. Отдельное спасибо за ссылку на cdecl.org: возможно, она мне понадобится для этого проекта. - person Dan Bron; 11.08.2015
comment
@DanBron: Вы также можете установить программу cdecl. Для Linux просто установите пакет cdecl. Для других ОС вы, вероятно, можете собрать его из исходного кода. - person Keith Thompson; 11.08.2015