Complex Declaration Diagrams

Arrays of Arrays Introduction

In this diagram, a is an array of 5 characters. Each element is a char and is 1 byte in size.
char a[5] = {'a', 'b', 'c', 'd', 'e'};

Here, b is an array of 5 integers. Each element is an int and is 4 bytes in size.
int a[5] = {1, 2, 3, 4, 5};

c is an array of 4 doubles. Each element is a double and is 8 bytes in size.
double a[4] = {1.1, 2.2, 3.3, 4.4};

d is an array of 3 Time structures. Each element is a Time structure and is 12 bytes in size.
struct Time
{
  int hours;
  int minutes;
  int seconds;
}

struct Time d[3] = { {3, 30, 0}, {9, 45, 0}, {10, 15, 0} };

Here, e is an array of 3 arrays of 5 characters. (A 3x5 array) Each element is an array of 5 characters and is 5 bytes in size.
We typically draw the array of arrays like this, which models what is being represented such as a 2D x/y grid, a matrix, or a table of some sort. Anything that might have rows and columns is a good candidate for this type of structure.
You access each character using two subscripts: e[row][column] where row and column are integers between 0 and 4. For example, the letter z would be accessed as e[1][4].

Arrays and Pointers Declaration Basics

What is the English equivalent of each declaration? In other words, what is the type of f1, f2, etc?

    Pointers/Arrays
  1. int f1;
  2. int *f2;
  3. int f3[3];
  4. int *f4[3];
  5. int (*f5)[3];
  6. int *(*f6)[3];
  7. int f7[3][4];
  8. int *f8[3][4];
  9. int (*f9)[3][4];
  10. int *(*f10)[3][4];
  11. int (*f11[3])[4];
  12. int *(*f12[3])[4];
  13. This is how to interpret the shapes used below. The diagrams assume 4-byte integers and 8-byte pointers.

    pointerint
    The shaded shape is the variable itself, i.e., not what's being pointed to. This should help you answer the sizeof questions. Also, the thick black lines indicate what is being pointed at, e.g. a single int/pointer or an array on ints/pointers.


    1. int f1; /* int */

    2. int *f2; /* pointer to int */
    3. Oftentimes, the pointer is actually pointing at an integer inside of an array. So this code:

      int a[3];
      int *f2 = a; /* same as &a[0] */
      
      would look like this, with the pointer pointing at the first element of the array and NOT the entire array:

      and this code:

      f2 = &a[1]; 
      
      would look like this:

      This is simply because f2 is a pointer to an int, NOT a pointer to an array of ints.


    4. int f3[3]; /* array of 3 ints */

    5. int *f4[3]; /* array of 3 pointers to int */

    6. int (*f5)[3]; /* pointer to an array of 3 ints */
    7. /* f5 points to the entire array */


    8. int *(*f6)[3]; /* pointer to an array of 3 pointers to int */
    9. /* f6 points to the entire array */


    10. int f7[3][4]; /* array of 3 arrays of 4 ints */

    11. int *f8[3][4]; /* array of 3 arrays of 4 pointers to int */

    12. int (*f9)[3][4]; /* pointer to an array of 3 arrays of 4 ints */
    13. /* f9 points to the entire array */


    14. int *(*f10)[3][4]; /* pointer to an array of 3 arrays of 4 pointers to int */
    15. Showing it with all of the pointers:

      /* f10 points to the entire array */


    16. int (*f11[3])[4]; /* an array of 3 pointers to arrays of 4 ints */
    17. The blue box is f11:

      The blue box is *f11:

      The blue box is **f11:

      The blue box is ***f11:

      /* each element of f11 points to an entire array */


    18. int *(*f12[3])[4]; /* an array of 3 pointers to arrays of 4 pointers to int */
    19. Showing another view with all of the pointers. Following the arrow from f12

      1. The BLUE box is *f12
      2. The next box is **f12
      3. The next box is ***f12
      4. The next box is ****f12
      /* each element of f12 points to an entire array */

      It doesn't matter how you draw the arrays, either vertically or horizontally, as long as you understand the diagrams.


    Here's a bonus. Specify the type in English. Then, write the declaration for f13 in C.