0
main()
{
int a[2][3][2]={{1,2},{9,8},{3,7}},{{2,2},{1,4},{5,4}};
printf("%d %d %d",a[1]-a[0],a[1][0]-a[0][0],a[1][0][0]-a[0][0][0]);
}

The output given in the book is 3 6 1. I am unsure about the working of 3-d array. Could someone please explain to me the entire process of the above code?

4
  • Considering a C book is a better option ! Commented Jan 12, 2014 at 5:29
  • 1
    You should be getting error, as this is improper initialization . Commented Jan 12, 2014 at 5:29
  • what is the proper initialization then? Commented Jan 12, 2014 at 5:32
  • stackoverflow.com/questions/9669206/… this should help you out. check the 2nd post(the answer) Commented Jan 12, 2014 at 5:38

2 Answers 2

2

Diagrammatically, the array initialized as:

int a[2][3][2] = { {{1,2},{9,8},{3,7}}, {{2,2},{1,4},{5,4}} };

(note the extra pair of braces that are necessary compared with the code in the question) looks like this in memory:

|                                   a                                   |
|                a[0]               |                a[1]               |
|  a[0][0]  |  a[0][1]  |  a[0][2]  |  a[1][0]  |  a[1][1]  |  a[1][2]  |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
|  1  |  2  |  9  |  8  |  3  |  7  |  2  |  2  |  1  |  4  |  5  |  4  |
+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
^                       ^                       ^                       ^ 
0x1000                  0x1010                  0x1020                  0x1030

The starting address is hypothetical and convenient rather than realistic; I'm assuming sizeof(int) == 4, which is the most common value but not guaranteed by the standard. In the discussion below, address ranges include the start address and exclude the end address.

What this diagram shows is that the 12 numbers are laid out linearly in memory as shown. The entire array, a has a size of 48 bytes, therefore, from address 0x1000 to 0x1030. The sub-array a[0] extends from address 0x1000 to 0x1018; the sub-array a[1] extends from 0x1018 to 0x1030. The sub-array a[0][0] extends from 0x1000 to 0x1008; a[1][0] from 0x1018 to 0x101C; and so on.

Now let's look at the printf() statement:

printf("%d %d %d", a[1]-a[0], a[1][0]-a[0][0], a[1][0][0]-a[0][0][0]);

We can observe (and my compiler did observe, as I expected it to), that the first two values are actually of type ptrdiff_t and therefore the correct format specifier is %td, not %d (though on a 32-bit platform, %d would be OK, and on a 64-bit platform, %ld would be OK, but to be correct on both, you need to use %td). It would also be better if the output ended with a newline.

It is easy to agree that the value of a[1][0][0] is 2, and the value of a[0][0][0] is 1, so the third number printed should be 1, and indeed that is the output.

Working backwards, a[1][0] is an array (of two int elements, so the size is 8 bytes) starting at address 0x1018; similarly, a[0][0] is an array starting at address 0x1000. However, because of the 'decay' of an array, these values are equivalent to int * (so *a[0][0] is equal to a[0[0][0] or the value 1) , so the raw difference in bytes (0x18 = 24) is scaled by the size of the object pointed at (int or 4), yielding the answer 6.

Similarly, a[1] is an array (of type int [3][2]), and so is a[0]. The difference is again 0x18 = 24 bytes, but this time, *a[1] is a pointer to an array of 2 int and is of size 8, therefore, so the answer is 3.

Thus, as expected, the correct output from the program is:

3 6 1

Further, although the addresses would be different, the calculation would be accurate if sizeof(int) == 2 or if sizeof(int) == 8 (or, indeed, any other size, though those are the main plausible candidates on modern general purpose hardware; DSP hardware might have sizeof(char) == sizeof(int) — and therefore sizeof(int) == 1 — and CHAR_BIT == 16 or even, perhaps, CHAR_BIT == 32).

Sign up to request clarification or add additional context in comments.

Comments

0

An array can be of any other type, including other arrays. So what you have is an array of two arrays of three arrays of two integers.

5 Comments

The difference will not be the number of bytes. It will be the number of units of the relevant size (the size of the objects the pointers point at).
@JonathanLeffler But wouldn't the difference between two addresses be the number of bytes between them?
No. The difference &a[1] - &a[0] is always 1, regardless of the type of a. That's not the expression used in the question, but in general, the difference between two pointers (to elements of the same array) is the number of units in the array between the two elements, not the number of bytes between the two elements (except for the case of byte-size elements — char, etc).
Joachim: Not in C, unless they're arrays of bytes. C pointers index in terms of the size of the object pointed at, and C array access is essentially another notation for C pointer math, so that difference will be in terms of sizeof a[0]. Websearch "c pointer array math"; several of the hits are right here on StackOverflow.
@JonathanLeffler After waking up properly, I do realize that you are of course correct.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.