Я новичок в C, и я пытаюсь выяснить некоторые C-объявления. Может ли кто-нибудь помочь мне объяснить смысл этих объявлений C?
double (*b)[n];
double (*c[n])();
double (*d())[n];
Я ценю помощь!
Я новичок в C, и я пытаюсь выяснить некоторые C-объявления. Может ли кто-нибудь помочь мне объяснить смысл этих объявлений C?
double (*b)[n];
double (*c[n])();
double (*d())[n];
Я ценю помощь!
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.
НТН
Основное правило для синтаксиса объявлений 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 и превращает ее в предложение естественного языка.
Попробуйте этот путь.
во-первых, вы должны быть знакомы с этими тремя символами:
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--
Есть два больших ресурса для понимания "C gibberish":
Вывод cdecl.org:
double (*c[n])()
: Синтаксическая ошибка (n
здесь недействительна)double (*c[])()
: объявить c как массив указателя на функцию, возвращающую double