1. The difference between arr and &arr - How to find size of an array in C without sizeof

    by Arjun Sreedharan

    Hey folks, Long time no C.

    Generally in C, this is how we find the length of an array arr :

    int n = sizeof(arr) / sizeof(arr[0]);
    


    Here we take the size of the array in bytes; then divide it by the size of an individual array element.


    Let’s get rid of sizeof and make things cool.


    Ever thought what’s the difference between arr and &arr?


    Let’s check that out by printing the memory addresses of both the pointers:
    image

    and here’s the output:
    image

    As you can see in the output, both arr and &arr point to the exact same memory location 0x244fdc4.



    Now, let’s increment both the pointers by 1 and check their memory address.


    Here’s the code to check for the memory address of arr + 1 and &arr + 1 :

    image

    and the output:
    image


    We find that:


    (arr + 1) points to 0x244fdc8 which is 4 bytes away from arr which points to 0x244fdc4.
    Since an int takes up 4 bytes, (arr + 1) points to the second element of the array.


    (&arr + 1) points to 0x244fdd8 which is 20 bytes away from arr which points to 0x244fdc4.
    (0x244fdd8 - 0x244fdc4 = 14 in hex = 20 in decimal)

    Taking the size of int into consideration, (&arr + 1) is 5 int-sizes away from the beginning of the array. 5 also happens to be the size of the array.
    So, (&arr + 1) points to the memory address after the end of the array.

    Now, we can deduce that while arr and &arr points to the same location, they are different in type.

    arr has the type int *, where as &arr has the type int (*)[size].

    &arr points to the entire array where as arr points to the first element of the array.

    image


    This brings us to something useful - length of the array.


    * (arr + 1) gives us the address after the end of the array and arr that of the first element of the array.
    Subtracting latter from former would thus give the length of the array.

    int n = *(&arr + 1) - arr;
    


    We can simplify this using array indexes (since x[1] == *(x+1) ):

    int n = (&arr)[1] - arr;
    



    PS:
    This works only for arrays, not when you take pointers (as in char *str for strings).

    void reverseStr(char *str){ 
      //wrong
      int strlength = (&str)[1] - str;
    }
    

    In this case &str is a pointer that points to the pointer str. Remember, in C arrays are not pointers.

    Addendum:

    I’d like to quote a question-answer i found on reddit / SO regarding the same topic.

    QAccessing the first address after an array seems to be undefined behavior. For example: if your array located at the end of an address-space, the referencing address causing an overflow and your resulting size could be anything. Then how could you access `(&arr)[1]` ?

    AC doesn’t allow access to memory beyond the end of the array. It does, however, allow a pointer to point at one element beyond the end of the array. The distinction is important.









  2. Disclaimer: The views expressed here are solely those of the author in his private capacity and do not in any way represent the views of the author's employer or any organization associated with the author.




















































Interesting Things:
exploresion.org







Recent Posts:
Simplicity is the ultimate sophistication. (Leonardo Da Vinci)
©
Arjun Sreedharan 2013