Вычисление C деклараций

Я новичок в C, и я пытаюсь выяснить некоторые C-объявления. Может ли кто-нибудь помочь мне объяснить смысл этих объявлений C?

double (*b)[n];
double (*c[n])();
double (*d())[n];

Я ценю помощь!

Ответы

Ответ 1

double (*b)[n];

b - указатель на массив из n удвоений

double (*c[n])();

c - массив из n указателей на функции, принимающие неопределенное количество аргументов и возвращающих double

double (*d())[n];

d - это функция, принимающая неопределенное число аргументов и возвращающая указатель на массив из n удвоений

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

 double (*d())[n];

что первое, что делается для d? Он вызывается с помощью(), поэтому это функция, которая принимает неопределенное количество аргументов и возвращает... что дело сделано с результатом? Он разыменовывается (*), поэтому он указывает на. Затем результат индексируется, поэтому он массив из n... что осталось? двойной, поэтому удваивает. Читая детали жирным шрифтом, вы получите ответ.

Посмотрим еще один пример

 void (*(*f)(int)[n])(char)

Здесь f сначала разыменован, поэтому он указатель на... он затем вызывается с (int), поэтому функция принимает int и возвращает, результат затем индексируется с помощью [n], поэтому массив из n. Результат разыменовывается снова, поэтому указывает на. Затем результат вызывается (char), поэтому выполняет функции char и возвращает (все оставлено пусто) void. Таким образом, f является указателем на функцию, принимающую int и возвращающую массив из n указателей на функции, принимающие char и возвращающие void.

НТН

Ответ 2

Основное правило для синтаксиса объявлений C "читается справа налево, а изнутри выпрыгивает вправо, оставляя пару скобок", т.е. начинаем самую глубоко вложенную пару круглых скобок, а затем начинаем искать право. Технически вы должны знать ассоциативность операторов, но она работает достаточно хорошо в большинстве ситуаций.

Теперь применим это (упрощенное) правило к вашему вопросу:


double (*b)[n];
         ^

b является

double (*b)[n];
        ^

указатель на

double (*b)[n];
           ^^^

и массив

double (*b)[n];
^^^^^^

двойников.


double (*c[n])();
         ^^^^

c - массив из

double (*c[n])();
        ^

указатели на

double (*c[n])();
              ^^

Функции

double (*c[n])();
^^^^^^

возврат дважды.


double (*d())[n];
         ^^^

d - функция

double (*d())[n];
        ^

возвращает указатель на

double (*d())[n];
             ^^^

массив

double (*d())[n];
^^^^^^

дубли


Там есть чистая утилита, найденная на большинстве * nixes, называемая cdecl, которая принимает строку декларации C и превращает ее в предложение естественного языка.

Ответ 3

Попробуйте этот путь.

во-первых, вы должны быть знакомы с этими тремя символами:

1. *  -- a pointer.
2. [] -- an array.
3. () -- a function.(notice: not parentheses)

возьмем в качестве примера "double (* d()) [n]".

первый шаг - найти идентификатор в объявлении, идентификатор - это имя переменной, здесь это "d".

(i)
-- what is "d"?
------------------------------------------------------------------------
look to the right side of the identifier, to see if there is a "[]" or a "()" :
...d[]...: d is an array.
...d()...: d is a function.

if neither, look to the left side, to see if there is a "*" :
...*d...: d is a pointer.
------------------------------------------------------------------------

теперь мы обнаружили, что d является функцией. используйте x для замены d(), тогда объявление станет "double (* x) [n]"

(ii)
-- what is "x"?
------------------------------------------------------------------------
repeat (i), we find that x is a pointer.
that means, d is a function returning a pointer.
------------------------------------------------------------------------

используйте y для замены * x, тогда объявление становится "double y [n]"

(iii)
-- what is "y"?
------------------------------------------------------------------------
repeat (i), we find that y is an array of n elements.
that means, d is a function returning a pointer to an array of n elements.
------------------------------------------------------------------------

используйте z для замены y [n], тогда объявление становится "double z"

(iv)
-- what is "z"?
------------------------------------------------------------------------
repeat (i), we find that z is a double.
that means, d is a function returning a pointer to an array of n double elements.
------------------------------------------------------------------------

см. другое выражение:

void (*(*f)(int)[n])(char)
1.
  we find f.
2.
  f is a pointer. *f -> a
  void (*a(int)[n])(char)
3.
  a is a function. a() -> b
  void (*b[n])(char)
  --f is a pointer to a function (with an int parameter)--
4.
  b is an array. b[] -> c
  void (*c)(char)
  --f is a pointer to a function returning an array (of n elements)--
5.
  c is a pointer. *c -> d
  void d(char)
  --f is a pointer to a function returning an array of n pointers--
6.
  d is a function returning void.
  --f is a pointer to a function returning an array of n pointers to functions (with a char parameter) returning void--

Ответ 4

Есть два больших ресурса для понимания "C gibberish":

Вывод cdecl.org:

  • double (*c[n])(): Синтаксическая ошибка (n здесь недействительна)
  • double (*c[])(): объявить c как массив указателя на функцию, возвращающую double