Thread: Mulitdimensional Arrays and Pointers

  1. #1
    Registered User
    Join Date
    Sep 2011
    Location
    Athens , Greece
    Posts
    357

    Mulitdimensional Arrays and Pointers

    Hello to all.

    I can't understand why this snippet

    Code:
    #include<stdio.h>
    
    int main(void)
    {
    	int arr2d[2][4] = { { 0 , 1 , 2 , 3 } , {4, 5 , 6 , 7}} , (*p)[4] , i=0;
    	
    	for( p = &arr2d[0]; p < &arr2d[2]; p++)
    	{
    		printf(" %d %d " , (*p)[i] , arr2d[0][0] );
    	}
    	
    	return 0;
    }
    Will advance the pointer Number_of_columns * sizeof(int) .

    Instead of this code

    Code:
    #include<stdio.h>
    
    int main(void)
    {
    	int arr2d[2][4] = { { 0 , 1 , 2 , 3 } , {4, 5 , 6 , 7}} , *p ;
    	
    	for( p = arr2d[0]; p < arr2d[1] + 4 ; p++)
    	{
    		printf("%d " , *p );
    	}
    	
    	return 0;
    }
    Which will advance pointer (p) 4 bytes (assuming in my system that int has 4 bytes size ) . The first snippet will process an column but the second a row. I know that... but I can't understand why in the second situation will advance the pointer with this size . (#COLUMNS * sizeof(int) ) . Due to & in front of arr2d[0] ?
    Yes but if we have p = &arr2d[0] ... arr2d[0] is a pointer , hence &arr2d[0] is a pointer to pointer but p is declared as a signle pointer without some object by the compiler. arr2d[0] is a pointer to arr2d[0][0] . Why this ?

    (*p)[4] is a double pointer declaration??? (cheating) .
    Last edited by Mr.Lnx; 11-02-2012 at 11:48 AM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Think about a struct containing an array instead for a moment.
    Code:
    struct foo {
        int arr[10];
    };
    
    struct foo arr[10];
    struct foo *p;
    for ( p = arr ; p < arr+10 ; p++ ) {
    }
    Do you understand by how much p++ advances through memory.

    The same applies when you have an array containing an array (which is what 2D arrays are).
    The only difference is that the pointer notation is rather more cryptic.
    Code:
    int arr2d[2][4] = { { 0 , 1 , 2 , 3 } , {4, 5 , 6 , 7}} , (*p)[4];
    // note that p = arr2d and p = &arr2d[0] are the same thing
    for ( p = arr2d ; p < arr2d + 2 ; p++ ) {
    }
    Instead of being "p is a pointer to a struct", you have instead "p is a pointer to an array of 4 int"

    Note that this is a very different thing to int *p[4], which is an array of 4 pointers to int.

    You can make 2D arrays with both kinds of pointers.
    The first is a single block of memory (much like an array of structs would be in contiguous memory).
    But each row of an array of pointers would need to be allocated separately. There is even no restriction on each 'row' of the array being the same length.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    (*p)[4] is not a double pointer declaration, nor is it "cheating". You simply aren't reading/understanding the type of p correctly in your first example. Declared on a line of it's own, it looks like this:
    Code:
    int (*p)[4];
    p is a pointer to array of 4 ints. That is different from a pointer to pointer to int. Arrays and pointers are not equivalent. See here: Arrays and Pointers, particularly 6.1-6.4b, and 6.8-6.13. Also, for help reading complex type declarations, I find this link helpful: Arrays and Pointers. There was another good link posted a few weeks back, but I can't find it.

    Now, in the first post, since p is a pointer to array of 4 ints, doing p++ increases the address by sizeof(array of 4 ints), or 4*sizeof(int). In the second post, p is a pointer to int, so p++ increments it by sizeof(int), not (#COLUMNS * sizeof(int)).

    Print out the relevant sizes of what p points to, ints, array rows, etc to help you understand. For snippet 1:
    Code:
    printf("sizeof(int) = %d\n", sizeof(int));
    printf("sizeof(*p) (i.e. the size of what p points to) = %d\n", sizeof(*p));
    printf("sizeof(arr2d[0]) = %d\n", sizeof(arr2d[0]));
    for( p = &arr2d[0]; p < &arr2d[2]; p++)
    {
        printf("p = %p (*p)[i] = %d arr2d[0][0] = %d\n" , (*p)[i] , arr2d[0][0] );
    }
    Compile and run:
    Code:
    sizeof(int) = 4
    sizeof(*p) (i.e. the size of what p points to) = 16
    sizeof(arr2d[0]) = 16
    p = 0xbfb9c9c8 (*p)[i] = 0 arr2d[0][0] = 0
    p = 0xbfb9c9d8 (*p)[i] = 4 arr2d[0][0] = 0
    Notice p increments by 16, the size of 4 ints, or one row in a 2-d array with 4 columns per row.

    For snippet 2:
    Code:
        printf("sizeof(int) = %d\n", sizeof(int));
        for( p = arr2d[0]; p < arr2d[1] + 4 ; p++)
        {
            printf("p = %p, *p = %d\n" , (void *)p, *p );
        }
    Output:
    Code:
    sizeof(int) = 4
    p = 0xbf991bbc, *p = 0
    p = 0xbf991bc0, *p = 1
    p = 0xbf991bc4, *p = 2
    p = 0xbf991bc8, *p = 3
    p = 0xbf991bcc, *p = 4
    p = 0xbf991bd0, *p = 5
    p = 0xbf991bd4, *p = 6
    p = 0xbf991bd8, *p = 7
    Notice that p increments by 4 bytes only, the size of one single int.
    Last edited by anduril462; 11-02-2012 at 12:31 PM. Reason: removed ungainly white space

  4. #4
    Registered User
    Join Date
    Sep 2011
    Location
    Athens , Greece
    Posts
    357
    Thank you both of you. I know how it works... but I think that I still face some difficulties.

    For instance... why the type of a[rows][cols] is different from (*p)[cols] ? they are int both of them.

    the first one is an array of arrays of course... the second one is an array of arrays too but the only different is that the
    elements have #cols distance among in the second situation with the pointer....
    Last edited by Mr.Lnx; 11-02-2012 at 05:41 PM.

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by Mr.Lnx View Post
    For instance... why the type of a[rows][cols] is different from (*p)[cols] ? they are int both of them.
    It seems you are not referring to declarations, but how you use them in code, i.e. how you would access an element from your array. arr2d and p are declared with different types, but the expressions arr2d[r][c] and (*p)[c] are of the same type. Why do you think they are different?

    EDIT:
    the first one is an array of arrays of course... the second one is an array of arrays too but the only different is that the
    elements have #cols distance among in the second situation with the pointer....
    Those variables are not of the same type. The second is most definitely not an array of arrays, it is a pointer to an array. Pointers and arrays are different. They have some similarities, and in some ways they overlap, but they are two different things. Did you read the C-FAQ link I provided in post #3?

    EDIT 2:
    Now, that doesn't mean that you can't use each of them in different expressions that result in the same type. But the variables themselves are not of the same type.
    Last edited by anduril462; 11-02-2012 at 05:50 PM.

  6. #6
    Registered User
    Join Date
    Sep 2011
    Location
    Athens , Greece
    Posts
    357
    I was confused because I thought that the type of (*p)[c] is int. I have read the C-FAQ about the pointers and arrays of course... there are differences ... you can't advance the name of an array as a pointer i.e arr2d++ or sizeof(arr2d) != sizeof(p) . In sizeof operator the prototype of C defines that it is not converted to a pointer.

    sizeof(int) = 4 bytes. I try to understand how does the pointer go 16 bytes in memory.

    The arr2d[c] array is type (*p) ? Due its declaration ? You said that the expressions are of the same type... (int both of them) but not the variables...

    so arr2d[c] variable is type of (*p). Right?
    Last edited by Mr.Lnx; 11-03-2012 at 03:30 AM.

  7. #7
    Registered User
    Join Date
    Sep 2011
    Location
    Athens , Greece
    Posts
    357
    I think I get it . p is a pointer to array not simple int. Is a double pointer .. point to array (which is a pointer on its first element) Anyway thank you.
    Last edited by Mr.Lnx; 11-03-2012 at 06:00 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pointers to pointers with arrays
    By Nurumla in forum C Programming
    Replies: 3
    Last Post: 07-18-2011, 11:53 PM
  2. Pointers to arrays
    By kargo in forum C++ Programming
    Replies: 4
    Last Post: 03-12-2011, 03:01 PM
  3. Replies: 7
    Last Post: 05-19-2010, 02:12 AM
  4. Passing pointers to arrays of char arrays
    By bobthebullet990 in forum C Programming
    Replies: 5
    Last Post: 03-31-2006, 05:31 AM
  5. Replies: 1
    Last Post: 12-07-2005, 10:23 PM