Приоритет оператора в определениях C

Википедия утверждает, что оператор [] предшествует оператору * при вычислении.

Тогда почему следующее утверждение:

char *a[3];

объявить массив из 3-символьных указателей, а не указатель на массив из 3-х символов в соответствии с приоритетом оператора?


person Community    schedule 22.01.2011    source источник
comment
Аналогично: stackoverflow. com/questions/859634/ В частности, см. ответ относительно cdecl   -  person    schedule 23.01.2011


Ответы (3)


Потому что, как говорит Википедия, [] имеет более высокий приоритет, чем *?

При обработке объявления a[3] обрабатывается как "массив из 3" перед обработкой *.

Чтобы объявить указатель на массив из трех символов, вы должны использовать круглые скобки, чтобы переопределить приоритет по умолчанию:

char (*a)[3];

Теперь скобки имеют приоритет над массивом.

person Jonathan Leffler    schedule 22.01.2011
comment
Но разве у деклараций нет отдельных правил интерпретации, как утверждается в других ответах? - person ; 22.01.2011
comment
@crypto, весь смысл синтаксиса объявления в C заключается в том, что используются имитаторы объявлений. - person AProgrammer; 22.01.2011
comment
@crypto: Нет, не совсем. Как говорит @AProgrammer, дизайн системы объявлений C таков, что используются имитаторы объявлений. Итак, a[0] — это char *, а *a[0] — это char. - person Jonathan Leffler; 23.01.2011
comment
@crypto: см. мой ответ ниже. Да, для объявлений существуют другие правила производства, но они следуют тем же правилам приоритета, что и выражения. - person John Bode; 23.01.2011

Вот грамматика декларатора, взятая из стандарта ( 6.7.5):

declarator:
    pointeropt direct-declarator

direct-declarator:
    identifier
    ( declarator )
    direct-declarator [ type-qualifier-listopt assignment-expressionopt ]
    direct-declarator [ static type-qualifier-listopt assignment-expression ]
    direct-declarator [ type-qualifier-list static assignment-expression ]
    direct-declarator [ type-qualifier-listopt * ]
    direct-declarator ( parameter-type-list )
    direct-declarator ( identifier-listopt )

pointer:
    * type-qualifier-listopt
    * type-qualifier-listopt pointer

type-qualifier-list:
    type-qualifier
    type-qualifier-list type-qualifier

parameter-type-list:
    parameter-list
    parameter-list , ...

parameter-list:
    parameter-declaration
    parameter-list , parameter-declaration

parameter-declaration:
    declaration-specifiers declarator
    declaration-specifiers abstract-declaratoropt

identifier-list:
    identifier
    identifier-list , identifier

Как видите, и [], и () связываются с декларатором до *. Возьмите декларацию

int *a[N];

Декларатор — *a[N], который соответствует приведенному выше шаблону pointeropt direct-declarator и, таким образом, анализируется как *(a[N]), поэтому a — это N-элементный массив указателей.

Подводить итоги:

T *a[N]      -- declares an N-element array of pointer to T
T (*a)[N]    -- declares a pointer to an N-element array of T
T *f()       -- declares a function returning pointer to T
T (*f)()     -- declares a pointer to a function returning T  
person John Bode    schedule 22.01.2011

Я запутался в вопросе - интерпретация объявления соответствует приоритету оператора. Если вам нужен указатель на массив, вы должны использовать круглые скобки, чтобы «связать * с идентификатором» перед привязкой [].

char (*a)[3];
person Michael Burr    schedule 22.01.2011