Converting address of an array to other data types

arrays, c, pointers

Solution

Note `&arr` is complete 3-dimensional char array's address, whereas `arr` points to first element that is 2-dimensional char array. Something like below in diagram:

 0xbf8ce2c6
+------------------+     ◄-- arr  =  0xbf8ce2c6  
|    0xbf8ce2f0    |  
|   +------------------+     ◄-- arr + 1 = 0xbf8ce2f0
|   |   0xbf8ce31a |   |
|   |   +------------------+      ◄-- arr + 2 = 0xbf8ce31a 
|   |   0xbf8ce344 |   |   |
|   |   |   +------------------+      ◄-- arr + 3 = 0xbf8ce344
|   |   0xbf8ce36e |   |   |   |
|   |   |   |  +------------------+      ◄-- arr + 4 = 0xbf8ce36e
|   |   |   |  |   |   |   |   |  |
+---|---|---|--|---+   |   |   |  |  Each are 7*6, 2-Dimensional 
    |   |   |  |       |   |   |  |  Consists Of 42 bytes 
    +---|---|--|-------+   |   |  |  
        |   |  |           |   |  |
        +---|--|-----------+   |  |
            |  |               |  |
            +--|---------------+  |
               |                  |
               +------------------+

 The diagram show: 
 1. How a 3-dimensional can be interpreted as series of 2-dimensional arrays
 2. Here (arr + i) points to a 2-D array 
 3. Notice difference between: (arr + i + 1) - (arr + i) = 0x2a = 42, where i = [0, 4]

Type of `&arr` is `char(*)[5][7][6]` that is address of char 3D-array of dimension `[5][7][6]`. Value-wise difference between `&arr` and `&arr + 1` is `5 * 7 * 6 * sizeof(char)` = `210`. Because size of `char[5][7][6]` is `5 * 7 * 6 * sizeof(char)`. In your code `&arr` points to 3-D array and `&arry + 1` next 3-D array (that doesn't exist in our code).

Check this working code at codepade:

int main()
{
    char arr[5][7][6];
    printf(" &arr  : %p", &arr);
    printf(" &arr+1: %p", &arr + 1);

    return 0;
}

Output:

 &arr  : 0xbf5dd7de
 &arr+1: 0xbf5dd8b0

Difference between `(&arr + 1) - (&arr)` = `0xbf5dd8b0 - 0xbf5dd7de` = `0xd2` = `210`.

In your second printf:

printf("%d\n", (char *)(&arr + 1) - (char *)&arr);

You typecasts addresses of type `char(*)[5][7][6]` to plain `(char*)`, and because sizeof `char[5][7][6]` is `210` both addresses are 210 far. (remember `sizeof(char) == 1`). This is the reason outputs: `210`

Now as I said in first statement, `arr` is address of first element that is a two dimensional array of chars. Type of `arr` is `char(*)[7][6]`. Now one element (two-dimensional array of size is `6 * 7 * sizeof(char) = 42`). (Note: you can think a 3-D array as one-d array where each element is a 2-d array).

In your third printf:

printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr);

You typecasts to unsigned value (but not to an address/pointer type). The difference between `arr + 1` and `arr` is `42 * sizeof(char)` = `42` (that is equals to size of `char[7][6]`). So the printf statement outputs: `42`.

Note: You should read sizeof (int) == sizeof (void*)?, because you are typecasting address to value. and this conversion is not fully defined. (my explanation is wrt your output and the output I have given).

For further clarification check below working code at codepade:

int main()
{
    char arr[5][7][6];
    printf(" arr  : %p\n", arr);
    printf(" arr+1: %p", arr + 1);

    return 0;
}

Output is:

 arr  : 0xbf48367e
 arr+1: 0xbf4836a8

Take difference between `(arr + 1) - (arr)` = `0xbf4836a8` - `0xbf48367e` = `0x2a` = `42`.

Last printf:

 printf("%d\n", (unsigned)(p + 1) - (unsigned)p);

Just take difference between `&arr+1` and `&arr` = `210` (similar to second printf) because `p` is pointer to 3-D char array (=`&arr`). And you are typecasting it to value type(not pointer type).

Additionally, (Just adding for understanding purpose, I guess reader will find it helpful),

Lets we learn one more difference between `arr` and `&arr` using sizeof operator that will help your to understand concept more deeper. For this first read: `sizeof` Operator

When you apply the `sizeof` operator to an array identifier, the result is the size of the entire array rather than the size of the pointer represented by the array identifier.

Check this working code at codepade:

int main()
{
    char arr[5][7][6];
    printf(" Sizeof(&arr)  : %lu and value &arr: %p\n", sizeof(&arr), &arr);
    printf(" Sizeof(arr)   : %lu and value arr : %p\n", sizeof(arr), arr);
    printf(" Sizeof(arr[0]): %lu and value a[0]: %p\n",sizeof(arr[0]), arr[0]);
    return 0;
}

Its output:

Sizeof(&arr)  : 4 and value &arr: 0xbf4d9eda
Sizeof(arr)   : 210 and value arr : 0xbf4d9eda
Sizeof(arr[0]): 42 and value a[0]: 0xbf4d9eda

Here `&arr` is just an address, and in the system address is of four-bytes and this is address of complete 3-dimensional char array.

`arr` is name of 3-dimensional array, and `sizeof` operator gives total size of array that is `210 = 5 * 7 * 6 * sizeof(char)`.

As I shown in my diagram `arr` points to first elements that is an 2-dimensional array. So because `arr` = `(arr + 0)`. Now using `*` Dereference operator at `(arr + 0)` gives value at address so `*(arr + 0) = arr[0]`.

- Notice `sizeof(arr[0])` gives `42` = `7 * 6 * sizeof(char)`. And this proofs conceptually a 3-dimensional array is noting but array of 2-dimensional array.

Because above in my answer at many time I written like: "size of `char[5][7][6]` is `5 * 7 * 6 * sizeof(char)`." so I am adding an interesting code below @codepade:

int main(){
 printf(" Char         : %lu \n", sizeof(char));
 printf(" Char[5]      : %lu \n", sizeof(char[6]));
 printf(" Char[5][7]   : %lu \n", sizeof(char[7][6]));
 printf(" Char[5][7][6]: %lu \n", sizeof(char[5][7][6]));

 return 1;
}

Output:

 Char         : 1 
 Char[5]      : 6 
 Char[5][7]   : 42 
 Char[5][7][6]: 210 

Problem

``` int main() { char arr[5][7][6]; char (*p)[5][7][6] = &arr; printf("%d\n", (&arr + 1) - &arr); printf("%d\n", (char *)(&arr + 1) - (char *)&arr); printf("%d\n", (unsigned)(arr + 1) - (unsigned)arr); printf("%d\n", (unsigned)(p + 1) - (unsigned)p); return 0; } ``` When I run the above code I get following output: ``` 1 210 42 210 ``` Why is the output not `1` in every case?

Original source

Related problems