Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusion in data types in a 2D array

Tags:

c

pointers

Here is a code which print the address of the first element of an 2D array followed by an addition of 1. Though all 4 base addresses are same but their addition with 1 is obviously not giving the same result due the their different "types". I can figure out the type for some(in case they are correct) but not for all.

int main()
{
    int array[4][3];
    printf("array %u\n",array);   //of type int(*)[3]
    printf("array+1 %u\n",array+1);
    printf("&array %u\n",&array);   //....???
    printf("&array+1 %u\n",&array+1);
    printf("array[0] %u\n",array[0]);    //of type int*
    printf("array[0]+1 %u\n",array[0]+1);
    printf("&array[0] %u\n",&array[0]); //....???
    printf("&array[0]+1 %u\n",&array[0]+1);
} 

Can you explain the "type" of each base address in detail in order to understand the pointer arithmetic involved after adding 1. A sample output for gcc machine is given below for quick reference.

array       3214383040 
array+1     3214383052 
&array      3214383040 
&array+1    3214383088 
array[0]    3214383040 
array[0]+1  3214383044 
&array[0]   3214383040 
&array[0]+1 3214383052 
like image 588
Terminal Avatar asked Mar 03 '11 13:03

Terminal


2 Answers

Having int array[4][3]; the following applies

array is an array with 4 elements. Each element is an array with 3 ints. In most circumstances using the name by itself makes the array decay to a pointer to its first element; then array becomes a pointer to arrays of 3 ints

array + 1 is a pointer to an array of 3 ints. Here array decays to pointer and the 1 refers to array of 3 int

&array is the address of the whole array. It points to objects of type array of 4 arrays of 3 ints

&array + 1 is the 2nd (which really does not exist) element of a pseudo-array of arrays of 4 arrays of 3 ints

array[0] is an array of 3 ints. It usually decays to a pointer to the first element

array[0] + 1 points to the 2nd int in array[0]

&array[0] address of an object of type array of 3 ints

&array[0]+1 2nd element of an array of arrays of 3 ints

PS. I'll try to make a drawing (ASCII) after lunch.


Hmmm ... drawing is tough :)

Before trying, I thought I could make a better drawing. This is the best I could come up with ...


    int array[4][3]        ........[aaabbbcccddd]........
                              where aaa, bbb, ccc, ddd are arrays of 3 ints'

    the [] represent the object itself; the {} represent pointers.

    array (object)         ........[AAABBBCCCDDD]........       int[4][3]
    array (decayed)    ==> ........{aaa}bbbcccddd........       int(*)[3]

    array + 1          ==> ........aaa{bbb}cccddd........       int(*)[3]

    &array             ==> ........{aaabbbcccddd}........       int(*)[4][3]
    &array + 1         ==> ........aaabbbcccddd{xxxxxxxxxxxx}........       int(*)[4][3]

    array[0] (object)      ........[AAA]bbbcccddd........       int[3]
    array[0] (decayed) ==> ........{a}aabbbcccddd........       int*

    array[0] + 1       ==> ........a{a}abbbcccddd........       int*

    &array[0]          ==> ........{aaa}bbbcccddd........       int(*)[3]
    &array[0] + 1      ==> ........aaa{bbb}cccddd........       int(*)[3]

like image 54
pmg Avatar answered Sep 22 '22 17:09

pmg


If you compile this as C++, you can use the typeid operator from the typeinfo STL library to get this information. For example, running this

#include <stdio.h>
#include <typeinfo>

void main()
{
     int array[4][3];
     printf("array %s\n",typeid(array).name());   //of type int(*)[3]
     printf("array+1 %s\n",typeid(array+1).name());
     printf("&array %s\n",typeid(&array).name());   //....???
     printf("&array+1 %s\n",typeid(&array+1).name());
     printf("array[0] %s\n",typeid(array[0]).name());    //of type int*
     printf("array[0]+1 %s\n",typeid(array[0]+1).name());
     printf("&array[0] %s\n",typeid(&array[0]).name()); //....???
     printf("&array[0]+1 %s\n",typeid(&array[0]+1).name());
}  

Gave me the following results

array int [4][3]
array+1 int (*)[3]
&array int (*)[4][3]
&array+1 int (*)[4][3]
array[0] int [3]
array[0]+1 int *
&array[0] int (*)[3]
&array[0]+1 int (*)[3]

This explains why adding 1 can increase the pointer by 4 bytes (a single int), 12 bytes (int[3]) or by 48 bytes (int[4][3]).

like image 45
irritate Avatar answered Sep 23 '22 17:09

irritate