0

I'm a university student, our teacher told us to tell the meaning of these pointers, but I only manage to figure out some of them:

1. int *p1;
2. int *p2[10];
3. int (*p3)[10];
4. int (*p4)();
5. int **p5();
6. int (**p6)[10];
7. int (**p7)();
8. int *(*p8)();
9. int (*p9[10])();
10. int **p10[10];

This is what I've figured out so far:

  • p1 is a pointer to an int
  • p2 is an array of 10 int pointer
  • p3 is a pointer that point to a static-array with 10 elements
  • p4 is a function pointer
  • p5 is not a pointer at all but a prototype of a function that returns int**
  • p6 is an array of 10 pointer-to-pointer
  • p7 is a pointer to a function pointer

Can you guys please help me? Because our teacher told us these will be on the exam

4 Answers4

4

cdecl.org can be used to decipher messy declarations like your examples:

int (*p9[10])(); => declare p9 as array 10 of pointer to function returning int

Failing that, you can use Clockwise/Spiral Rule to grind through them manually.

Aydan Haqverdili
  • 406
  • 1
  • 4
  • 13
0

All 7 pointers are correctly determined, but you should specify the parameter type and the return type with.

For example:

  1. int **p5(); - function with no arguments, returning a pointer to pointer to int.

  1. int *(*p8)(); - pointer to function with no arguments, returning a pointer to int.
  2. int (*p9[10])(); - array of 10 pointer to function with no arguments, returning int.
  3. int **p10[10]; - array of 10 pointer to pointer to int.

If I were a compiler I could hint the empty parameter list, like f.e. clang does:

"warning: this function declaration is not a prototype [-Wstrict-prototypes]"

Use (void) instead of () , when using these constructs in practice.


Note if you are on an exam, think of David Anderson`s Clockwise/Spiral Rule, as illustrated here.

0

1>pointer to integer

int *p1;
```````````````````````````````````````
2>array of 10 pointer which point to integer
`````````````````````````````````
int *p2[10];
`````````````````````````````````
3> pointer to an array of 10 integers
```````````````````````
int (*p3)[10]
``````````````````````````````````````
4> pointer to function that takes void argument and return integer
`````````````
int (*p4)();
```````````````
5>> is a prototype(deceleration)  of a function which called p5 and returns int** 
````````````
int **p5();
``````````
6>> is an array of 10 pointer-to-pointer which point to integer values
`````````
 int (**p6)[10]
````````
7>>is pointer to pointer to function that takes void argument and return int
``````````````
int (**p7)();
````````````````
8>>pointer to function that takes void argument and return address or pointer
`````````````````
int *(*p8)();
`````````````
9>>array of 10 pointers to functions that take void argument and return an integer
``````````````````
 int (*p9[10])();
```````````````
10>> it indicate to the first element in an array of 10 pointers which point to integer values 
```````````
int **p10[10];
```````````
sara hamdy
  • 402
  • 2
  • 12
0

There are some techniques to reading and understanding complex declarations. There's a trick known as the "clockwise spiral rule", where you start with the identifier and spiral outward starting with whatever's immediately to the right. For example, given the declaration

int *(*a[N])(void);

we'd trace it as:

                 +-----------------------+
                 | +-----------+         |
                 | | +-------+ |         |
                 | | | +-+   | |         |
                 | | | | |   | |         |
             int * ( * a [N] ) ( void )  |
             ^   | | |   |   | |         |
             |   | | +---+   | |         |
             |   | +---------+ |         |
             |   +-------------+         |
             +---------------------------+

or

                   a                -- a
                   a[N]             -- is an N-element array
                  *a[N]             -- of pointers
                 (*a[N])(    )      -- to functions taking
                 (*a[N])(void)      --   no parameters
                *(*a[N])(void)      -- returning pointer to
            int *(*a[N])(void);     -- int

Remember that the postfix subscript [] and function call () operators have higher precedence than the unary dereference * operator, so expressions like *a[i] and *f() are parsed as *(a[i]) and *(f()) - we're dereferencing the results of a[i] and f(). If a points to an array, then we need to index into the result of *a, so we need to use parentheses to explicitly group * with a - (*a)[i]. Similarly, if f points to a function, then we need to call the result of *f, so we have to write (*f)().

Here's an example with multiple indirection:

int **foo(void);

which breaks down as

      foo             -- foo
      foo(    )       -- is a function taking
      foo(void)       --   no parameters
     *foo(void)       -- returning a pointer
    **foo(void)       -- to a pointer
int **foo(void);      -- to int

You'd recursively apply these rules to any function parameters. Here's the declaration of the signal function from the standard library:

void (*signal(int sig, void (*func)(int)))(int);

which reads as

       signal                                    -- signal
       signal(                          )        -- is a function taking
       signal(    sig                   )        --   parameter sig
       signal(int sig                   )        --     is an int
       signal(int sig,        func      )        --   parameter func
       signal(int sig,       *func      )        --     is a pointer
       signal(int sig,      (*func)(   ))        --     to a function taking
       signal(int sig,      (*func)(int))        --       parameter unnamed is an int
       signal(int sig, void (*func)(int))        --     returning void
     (*signal(int sig, void (*func)(int)))       -- returning a pointer
     (*signal(int sig, void (*func)(int)))(   )  -- to a function taking
     (*signal(int sig, void (*func)(int)))(int)  --   unnamed parameter is an int
void (*signal(int sig, void (*func)(int)))(int); -- returning void

There are also some substitution tricks you can play with. If you need to figure out how to declare an array of pointers to functions returning pointers to other functions returning pointers to arrays of pointers to int, start with an array of T:

T a[N];   // a is an array of T

This is going to be an array of pointers to something, so replace T with a pointer type P:

P *a[N];  // a is an array of pointer to P

Each a[i] is going to be a pointer to a function, so replace P with the function type F:

F (*a[N])( );

Each of these functions returns a pointer, so replace F with another pointer type P:

P *(*a[N])( );

Each of these pointers points to another function, so

F (*(*a[N])( ))( );

Those functions return pointers, so we replace F with another pointer type P:

P *(*(*a[N])( ))( );

Replace P with an array type A:

A (*(*(*a[N])( ))( ))[M];

And from here we can skip straight to the end:

int *(*(*(*a[N])( ))( ))[M];
John Bode
  • 119,563
  • 19
  • 122
  • 198