1

I created a 3d array

a[2][3][2]

Now when I try to print

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

I get 3 as the output.

What I understand is that a[1] gives me the address of a[1][0][0] element and a[0] the address of a[0][0][0].

Let Address of a[0][0][0] is BA then Address of a[1][0][0] is BA + 4*2*3 where 4 byte is the memory space of an integer datatype

I was expecting the result to be 6.

Similarly I tried

printf("%d",(&a + 1) - &a);

and the output received was 1.

Where am I going wrong?

Edit 1: Entire Code

#include<stdio.h>

int main(){
    int a[2][3][2] = {{{1,2},{3,4},{5,6}},{{7,8},{9,10},{11,12}}};
    printf("%d",a[1]-a[0]);
    return 0;
}
shad3
  • 13
  • 3

2 Answers2

2

What I understand is that a[1] gives me the address of a[1][0][0] element and a[0] the address of a[0][0][0].

This is wrong a[0] will give the address of the first 2D array. The address of the first 2D array and the address of a[0][0][0] might be co-incident, but they are not the same.

Specifically &a +1 is not equal to &a[0][0][0] +1

Rishikesh Raje
  • 8,556
  • 2
  • 16
  • 31
  • This answer would be better if you distinguished between "pointers" (which have types), and "addresses" which are just, well, addresses. Thus I would phrase it as the *addresses* are the same - but the types are not (and hence subtraction is different). – Martin Bonner supports Monica Mar 24 '17 at 10:23
  • @Rishikesh Raje Yes I get that &a + 1 will give me the address of the memory location after the 3d array i.e. &a[2][3][2] + 1. But is it coming 1 because it will consider the complete size of array a in subtraction? Something like if ((BA + 2*3*2*4)-BA))/sizeof(a) – shad3 Mar 24 '17 at 11:24
0

Let's break the expression a[1] - a[0] apart:

a[1] - refers to the second [3][2] array.
a[0] - refers to the first [3][2] array.

Now, when arrays are used in most contexts, they decay into pointers to the first element. So a[i] will decay into a pointer to a 2d array int(*)[2].

The difference is calculated in sizeof(int[2]) as dictated by pointer arithmetic. And you can see that there are 3 units of int[2] in the range [a[0], a[1]).

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • Thank You for breaking and simplifying. I am new to pointer and addresses hence it is really helpful – shad3 Mar 24 '17 at 10:41
  • a[1] and [0] point to two separate objects. The behavior is undefined as mentioned in 6.5.6 §8 Some similar additional reasoning: http://stackoverflow.com/a/6291590/4082723 ,if I wasn't clear. – 2501 Mar 24 '17 at 11:23
  • @2501 a[1] decays to a pointer that is one past the end of a[0]. The arithmetic is well defined. – StoryTeller - Unslander Monica Mar 24 '17 at 11:39
  • @2501 - You can consult 6.5.6/9 if my assurance alone is not enough. – StoryTeller - Unslander Monica Mar 24 '17 at 11:48
  • The rule you mentioned says: *When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object*. Pointers a[1] and a[0] don't belong to the same array object. They each point to a separate arrays, that both happen to belong to another array `a`, but that doesn't make them the same array object. – 2501 Mar 26 '17 at 07:36
  • @2501 - `a[0]` decays to a pointer to the start of `a[0]`. `a[1]` decays to a pointer to start of `a[1]`. Since there's no padding, due to `a` itself being an array, `a[1]` decays to a pointer that is exactly one past the end of the array `a[0]`. They are also pointers to the same type of object, and by 6.5.6/9 the subtraction is allowed. There really is nothing more to it. – StoryTeller - Unslander Monica Mar 26 '17 at 07:51
  • You're forgetting that they are two separate array objects, just like two members of a struct are two separate object and must not be used in pointer arithmetic, otherwise ub. – 2501 Mar 28 '17 at 07:41
  • @2501 - I'm not forgetting anything. The standard places no prohibitions with regard to how one obtains a pointer to "one past the end" of an array. As long as one uses *that* address, there is no UB. If however, the OP was to subtract non-consecutive elements like `a[2]` and `a[0]`, *then* the behavior would be undefined as you say. – StoryTeller - Unslander Monica Mar 28 '17 at 07:48