В отличие от обычного метода обучения, я предлагаю вам начать с за пределами в. Признайте общую структуру декларации и приступайте к уточнению: замените крупнозернистые «капли», которые вы видите более подробными. Другими словами, переходите синтаксис из корня дерева синтаксиса к листьям, вместо того, чтобы пытаться выбрать правильный лист и работать снизу вверх.
Общая структура декларации (которая имеет один описатель) является:
TYPE WHATEVER;
WHATEVER
в настоящее время объявлены, связанные с TYPE
.
Обратите внимание, что TYPE
является int
, поэтому WHATEVER
имеет тип int
. И WHATEVER
имеет общую форму (W1)(W2)
: две синтаксические единицы в скобках, независимо от 1 и всех 2:
int (W1)(W2);
Здесь, W1
является то, что объявляется, и это функция, возвращающая int
, которая выводится список W2
параметров , Последнее фактически означает int *
:
int (W1)(int *);
Таким образом W1
является функция, возвращающая int
который принимает int *
. Но W1
на самом деле *W3
, что делает W3
указателем на W1
.
int (*W3)(int *);
W3
является указателем на функцию, возвращающую int
который принимает int *
.
И W3
на самом деле f[]
, так f
массив неопределенного размера типа W3
«s:
int (*f[])(int *);
f
массив неопределенного размера указателей на функцию, возвращающую int
, который принимает int *
.
Совет: Как мы знаем, что W1
это на самом деле не W3[]
где W3
тогда *f
? Это связано с тем, что оператор построения типа [...]
синтаксически подобен оператору индексирования постов постфиксации [...]
, а построение типа *
аналогично унарному оператору разыменования *
. Унарный оператор имеет нижнюю предопределенность , чем оператор постфикса. Когда мы видим *X[]
, мы знаем, что это означает *(X[])
, а не (*X)[]
. Символы *X
не образуют синтаксическую единицу в этой фразе. Если мы хотим второго значения, мы должны использовать круглые скобки.
дерево синтаксис:
declaration
| |
+------------+ +----------------+
| |
specifier-qualifier list -- TYPE declarator -- WHATEVER
| | |
int +-----+ |
| |
function -- W1 params -- W2
| |
pointer -- W3 (int *)
|
array -- f
Внимательные символы, такие как W3
только этикетки для узлов при обходе от корня к листьям. Имя, объявленное в объявлении C
, находится где-то внизу дерева, в отличие от некоторых других языков. По мере того как go deeper в Дерево, мы на самом деле начинаем из типа, поэтому, наконец, когда мы приходим на дно, мы знаем самые важные вещи: объявляется f
, и в целом это массив чего-то.
отступы! Отступы! Отступы! –