Thread: Pointers and Arrays.

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

    Pointers and Arrays.

    Hello to all. I have a single question. I have read the C faq .

    The Standard says that if I have an array for example

    Code:
    int arr[3]={1,2,3}
    the expression arr yiels a pointer .... except when arr appears in a sizeof like sizeof(arr) which gives 12 and & operator.....

    Why sizeof(&arr) gives 8? The same with a pointer size..... According to prototype &arr is not a pointer?

    thank you in advance.

  2. #2
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    No.
    arr is a pointer.
    &arr is the adrress of the pointer
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  3. #3
    Registered User dariyoosh's Avatar
    Join Date
    Nov 2012
    Location
    Iran / France
    Posts
    38
    In addition, what sizeof returns depends on the platform and also glibc installed on the system (processor X86 or x86_64). Here is what I get when I run the following on a Linux system (Fedora Core 17 X86_64; ldd (GNU libc) 2.15)

    Code:
    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
        int array[3] = {1,2,3};
        printf("sizeof(array) = %lu\n", sizeof(array));
        printf("sizeof(array[0]) = %lu\n", sizeof(array[0]));
        printf("sizeof(int) = %lu\n", sizeof(int));
        printf("sizeof(int *) = %lu\n", sizeof(int *));
        printf("size_t = %lu\n", sizeof(size_t));
        
        return 0;
    }
    Which returns the following (depending on your system/platform you may get different result)

    Code:
    $ gcc -Wall testscript.c -o testscript
    $ ./testscript
    sizeof(array) = 12
    sizeof(array[0]) = 4
    sizeof(int) = 4
    sizeof(int *) = 8
    size_t = 8
    $
    As far as I remember according to C99, size_of is at least 16 bits (therefore 8 is returned by sizeof)

    Regards,
    Dariyoosh

  4. #4
    Registered User
    Join Date
    Sep 2011
    Location
    Athens , Greece
    Posts
    357
    Thank you guys.

    dariyoosh my problem is not the difference in the value due to implemention issues from a particular platform.

    I have read that whenever array appears in an expression it will be converted to pointer on the first its element.

    THe exceptions are when we have sizeof , & and literal initializer..... And I can't understand what the exception is for &array
    because we get a pointer size when we apply sizeof... I hope to make my query understood :-/

    thank you for your time.

  5. #5
    Registered User dariyoosh's Avatar
    Join Date
    Nov 2012
    Location
    Iran / France
    Posts
    38
    Quote Originally Posted by Mr.Lnx View Post
    THe exceptions are when we have sizeof , & and literal initializer..... And I can't understand what the exception is for &array
    because we get a pointer size when we apply sizeof... I hope to make my query understood :-/
    I'm not sure whether I understood your point

    An array, let's an int array, is a pointer to its first cell. Therefore it includes the address of its first cell, and that's why the sizeof operator returns 8 (sizeof(array) = 8). That's why I said it depends on architecture, because sizeof (int) an sizeof(an address of int) are not necessarily equal.
    array is a pointer (in the case of this example int *), &array is the address of the pointer, in other words, a pointer of pointer (int **), so again sizeof return 8 because again, here we are talking about the sizeof an address.

    Is it what you were asking for?

    Regards,
    Dariyoosh

  6. #6
    Registered User
    Join Date
    Sep 2011
    Location
    Athens , Greece
    Posts
    357
    Yes. But I do not agree with the term pointer to pointer for an &array.

    An adress is not always equivalent with a pointer

    Check 2D arrays for example.... is there any double pointer???

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by std10093 View Post
    No.
    arr is a pointer.
    &arr is the adrress of the pointer
    That is 100% wrong.

    arr is an array of three ints. So sizeof(arr) gives a result that is three times sizeof(int). If sizeof(int) is 4, then sizeof(arr) is 12.

    &arr is a pointer to (an array of three ints) - I've inserted braces to show what the pointer points at.

    If arr is used in a context where a pointer to int is expected, then "arr" is converted to the value &arr[0]. &arr[0] has type "pointer to int" and value equal to the address of arr[0].
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  8. #8
    Registered User dariyoosh's Avatar
    Join Date
    Nov 2012
    Location
    Iran / France
    Posts
    38
    Quote Originally Posted by Mr.Lnx View Post
    Yes. But I do not agree with the term pointer to pointer for an &array
    That is very sad.

    Quote Originally Posted by Mr.Lnx View Post
    An adress is not always equivalent with a pointer
    An address is the content/value of a pointer. Saying an address is/is not equivalent with a pointer has no meaning.

    Quote Originally Posted by Mr.Lnx View Post
    Check 2D arrays for example.... is there any double pointer???
    There are for sure double pointers. Each row is an array, therefore a pointer to the address of its first element. And each element is also an array therefore again a pointer to the address of its first element (which is not an array).

    Conclusion: a 2D array variable's name = a pointer to a pointer

    Regards,
    Dariyoosh
    Last edited by dariyoosh; 12-21-2012 at 03:31 PM.

  9. #9
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by dariyoosh View Post
    That is very sad.
    "That" also happens to be correct. The address of an array is not a pointer to pointer.

    Quote Originally Posted by dariyoosh View Post
    An address is the content/value of a pointer. Saying an address is/is not equivalent with a pointer has no meaning.
    The value of an uninitialised pointer is not an address. Even accessing the value of the pointer gives undefined behaviour. Trying to use that value as an address gives undefined behaviour.

    Quote Originally Posted by dariyoosh View Post
    There are for sure double pointers. Each row is an array, therefore a pointer to the address of its first element. And each element is also an array therefore again a pointer to the address of each first element (which is not an array).

    Conclusion: 2D array = a pointer to a pointer
    You are starting with the incorrect assumption that a 1D array is a pointer. It is not. A 2D array is an array of 1D arrays. It is not a pointer to a pointer.

    By your (flawed) logic, you would expect this code to compile.
    Code:
    int main()
    {
          int x[3][3];
          int **p = x;
          p = x;
    }
    However, all standard-conformant compilers will reject the second and third lines of main().
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  10. #10
    Registered User
    Join Date
    Sep 2011
    Location
    Athens , Greece
    Posts
    357
    dariyoosh if you want to change your opinion ... the only array that you have double pointers is here ->

    Code:
     int *array[3]= { pointer1 , pointer2 , pointer3};
    so for this case &pointer1 is actually a double pointer(is something quite different with the discussion of 2D arrays though).... You should notice that if you have a 2D array for example arr2d[2][3]

    arr2d , &arr2d has the same address so where is the double pointer? The only difference is on the type.

    p.s When you use the arr2d as a pointer it has type int (*) [NUM_COLS];
    Last edited by Mr.Lnx; 12-21-2012 at 03:51 PM.

  11. #11
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by dariyoosh View Post

    There are for sure double pointers. Each row is an array, therefore a pointer to the address of its first element. And each element is also an array therefore again a pointer to the address of its first element (which is not an array).

    Conclusion: a 2D array variable's name = a pointer to a pointer

    Regards,
    Dariyoosh
    So you're saying that this always works?
    Code:
    void function (int **foo);
    
    int main(void) {
        int foo[5][5];
        function(foo);
        return 0;
    }
    Try and compile that, you'll see how wrong it is. Confusion arises because pointers can simulate arrays, but the C standard has specific requirements for how real array types decay. An array is indeed converted to a pointer to the first element in many contexts. This conversion applies only to the first level of indirection, though, so in a 2d-array the row dimension will become a pointer, but the column dimension will stay an array type. The subsequent array types for other dimensions is the reason why you are required to supply a dimension size when making a parameter for a 2d-array in a function.

    Now, the reason that & (address of) is an exception to the "array decays to a pointer to the first element" rule of thumb is because of the type of the expression: &array is a pointer to an array, not unlike any other expression involving &. So for example, that might look like:
    Code:
     char (*ptr2ar)[50];
    char ar[50] = "Goodbye cruel world!";
    ptr2arr = &ar;
    For more information, consult the C FAQ. Of particular interest is Question 6.12.

  12. #12
    Registered User dariyoosh's Avatar
    Join Date
    Nov 2012
    Location
    Iran / France
    Posts
    38
    @whiteflags

    Many thanks for this clarification.

    Regards,
    Dariyoosh

  13. #13
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Quote Originally Posted by grumpy View Post
    That is 100% wrong.
    101% I would say! Am I blind? :O
    Thanks for the correction grumpy!
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  14. #14
    Registered User
    Join Date
    Sep 2011
    Location
    Athens , Greece
    Posts
    357
    Code:
    #include<stdio.h>
    
    int main(void)
    {
    	int arr[3]={1,2,3};
    	int (*p)[3];
    	
    	p = &arr;
    	
    	printf("%d" , **p);
    
    return 0;
    }
    what about this?

  15. #15
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by Mr.Lnx View Post
    Code:
    #include<stdio.h>
    
    int main(void)
    {
    	int arr[3]={1,2,3};
    	int (*p)[3];
    	
    	p = &arr;
    	
    	printf("%d" , **p);
    
    return 0;
    }
    what about this?
    Yeah, when you dereference the pointer, you might be using the array in a decaying context.

    The point is that you can't go from T (*)[N] -> T** -> T only T(*)[N] -> T[N] -> T

    You will find that is a significant difference in how the compiler gets to some element. [edit] Here, maybe this will help:
    Code:
    #include <stdio.h>
    
    int main(void)
    {
        int (* p2ar)[3];
        int ar[3] = { 1, 2, 3 };
        p2ar = &ar;
        printf("sizeof int *   = %lu\n", (unsigned int) sizeof(int *));
        printf("sizeof int     = %lu\n", (unsigned int) sizeof(int));
        printf("sizeof *p2ar   = %lu\n", (unsigned int) sizeof(*p2ar));
        printf("sizeof **p2ar  = %lu\n", (unsigned int) sizeof(**p2ar));
        return 0;
    }
    
    /*
    My output:
    
    sizeof int *   = 4
    sizeof int     = 4
    sizeof *p2ar   = 12
    sizeof **p2ar  = 4
    */
    Clearly based on the output alone, there is an array type involved, despite the syntax choices. [/edit]
    Last edited by whiteflags; 12-21-2012 at 06:14 PM.

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. Replies: 7
    Last Post: 05-19-2010, 02:12 AM
  3. pointers and arrays
    By murali026 in forum C++ Programming
    Replies: 1
    Last Post: 07-20-2009, 11:36 PM
  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. pointers to arrays
    By gaah in forum C++ Programming
    Replies: 16
    Last Post: 03-08-2005, 05:59 PM