Ответ 1
Вы эффективно определили h
как:
void h(int(int)) {}
Параметр интерпретируется как неназванный указатель функции, который принимает int
и возвращает int
. Когда вы пытаетесь передать ему 42
, компилятор жалуется, что вы пытаетесь сделать указатель на функцию из целого числа.
Я думаю, что вы просите, как компиляторы обрабатывают (неназванные) типы указателей функций и их, возможно, двусмысленные парсы. Ваш вопрос связан с самым досадным анализом на С++.
Там они решили, что всякий раз, когда возникает неоднозначность между типом указателя функции и другим способом анализа, он интерпретируется как указатель на функцию. Они сделали это, потому что есть другие способы устранения неоднозначности, если вы не хотите, чтобы он был указателем на функцию (например, - окружал его в круглых скобках, использовал {} синтаксис инициализатора и т.д.).
Вникая в специфику того, как автор синтаксического анализа может справиться с этим анализом, здесь лексический анализатор и грамматика для C11: http://quut.com/c/ANSI-C-grammar-l-2011.html В ваш пример, до typedef, x
будет токеном IDENTIFIER
, а после, это будет токен TYPEDEF_NAME
, потому что анализатор информируется через таблицу символов, что x
теперь является типом. В этом конкретном случае разбор недвусмыслен. "Обратная связь с конвейером", о которой вы, похоже, ссылаетесь, происходит через таблицу символов в этом случае, когда лексический анализатор информируется о контексте более высокими уровнями, которые влияют на его вывод по мере продвижения компиляции.
EDIT: Эти три статьи, найденные OP, описывают эту проблему и как она решается некоторыми C-синтаксическими анализаторами/компиляторами очень красиво. В принципе, контекстная свободная грамматика (CFG), которая только принимает/генерирует легальный синтаксис C, может быть почти указана. С появлением таблицы поиска по областям, которая позволяет лексическому анализатору правильно различать идентификаторы и имена typedef, тогда CFG [и, что более важно, LALR (1) parser (например, - yacc generated)], который принимает или генерирует легальный C может быть указан синтаксис.
Здесь еще более страшный пример, чем OP:
typedef int x;
int main() { x x = 5; return x; } /* crazily enough this is legal C syntax and a well formed C program */