Вычисление 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