Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Figuring out C Declarations like: double (*b)[n]

Tags:

c

declaration

I'm trying to figure out some C declarations. What is the meaning of these C declarations?

double (*b)[n];
double (*c[n])();
double (*d())[n];
like image 281
Joe Crawley Avatar asked Nov 06 '12 08:11

Joe Crawley


4 Answers

double (*b)[n];

b is a pointer to an array of n doubles

double (*c[n])();

c is an array of n pointers to functions taking unspecified number of arguments and returning double

double (*d())[n];

d is a function taking unspecified number of arguments and returning a pointer to an array of n doubles

In general, in order to parse these kind of declarations in your head, take the following approach. Let's see the last declaration, for example

 double (*d())[n];

what is the first thing that is done to d? It is called with (), therefore it's a function taking unspecified number of arguments and returnig... what's the thing done with the result? It is dereferenced (*), therefore it's a pointer to. The result is then indexed, therefore it's an array of n... what's left? a double, therefore of doubles. Reading the parts in bold, you'll get your answer.

Let's see another example

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

Here, f is first dereferenced, therefore it's a pointer to... it's then called with (int), therefore a function taking int and returning , the result is then indexed with [n], so an array of n. The result is dereferenced again, so pointers to. Then the result is called by (char), so functions taking char and returning (all is left is void) void. So f is a pointer to a function taking int and returning an array of n pointers to functions taking char and returning void.

HTH

like image 129
Armen Tsirunyan Avatar answered Oct 29 '22 19:10

Armen Tsirunyan


The basic rule to parse C declarations is "read from right to left and the inside out jumping toward the right when leaving a pair of parenthesis", i.e. start the the most deeply nested pair of parenthesis and then work yourself out looking toward the right. Technically you must know operator associativity, but it works well enough in most situations.

Now lets apply this (simplified) rule to your question:


double (*b)[n];
         ^

b is a

double (*b)[n];
        ^

pointer to

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

and array

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

of doubles.


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

c is an array of

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

pointers to

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

functions

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

returning double.


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

d is a function

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

returning a pointer to

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

an array of

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

doubles


There's a neat utility found on most *nixes, called cdecl, which takes a C declaration string and turns it into a natural language sentence.

like image 43
datenwolf Avatar answered Oct 29 '22 19:10

datenwolf


Let try this way.

first, you should be familiar with these three symbols:

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

we take "double (*d())[n]" as an example.

the first step is to find out the identifier in the declaration, an identifier is the name of variable, here it is "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.
------------------------------------------------------------------------

now we've found that d is a function. use x to replace d(), then the declaration becomes "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.
------------------------------------------------------------------------

use y to replace *x, then the declaration becomes "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.
------------------------------------------------------------------------

use z to replace y[n], then the declaration becomes "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.
------------------------------------------------------------------------

let's see another expression:

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--
like image 4
Yuankun Avatar answered Oct 29 '22 19:10

Yuankun


There are two great resources to understand "C gibberish":

  • http://cdecl.org/ - Online service that translates "C gibberish ↔ English"
  • The "Clockwise/Spiral Rule" by David Anderson if you want to understand what better what is going on

Output of cdecl.org:

  • double (*c[n])(): Syntax error (n is not valid here)
  • double (*c[])(): declare c as array of pointer to function returning double
like image 1
Aaron Digulla Avatar answered Oct 29 '22 18:10

Aaron Digulla