Categories
arrays c pointers sizeof

How to find the ‘sizeof’ (a pointer pointing to an array)?

378

First off, here is some code:

int main() 
{
    int days[] = {1,2,3,4,5};
    int *ptr = days;
    printf("%u\n", sizeof(days));
    printf("%u\n", sizeof(ptr));

    return 0;
}

Is there a way to find out the size of the array that ptr is pointing to (instead of just giving its size, which is four bytes on a 32-bit system)?

8

  • 92

    I’ve always used parens with sizeof – sure it makes it look like a function call, but I think it’s clearer.

    Jan 29, 2009 at 16:44

  • 21

    Why not? Do you have something against superfluous parentheses? I think it reads a little more easily with them, myself.

    Jan 29, 2009 at 16:44

  • 6

    @Paul: well .. assuming the left hand side of that call is a pointer to int, I’d write it as int *ptr = malloc(4 * sizeof *ptr); which to me is far clearer. Less parens to read, and bringing the literal constsant to the front, like in maths.

    – unwind

    Jan 29, 2009 at 17:32

  • 4

    @unwind – don’t allocate an array of pointers when you meant an array of ints!

    Jan 29, 2009 at 17:47

  • 6

    There is no “pointer pointing to an array” here. Just a pointer pointing to an int.

    – newacct

    Feb 28, 2013 at 19:01

328

No, you can’t. The compiler doesn’t know what the pointer is pointing to. There are tricks, like ending the array with a known out-of-band value and then counting the size up until that value, but that’s not using sizeof().

Another trick is the one mentioned by Zan, which is to stash the size somewhere. For example, if you’re dynamically allocating the array, allocate a block one int bigger than the one you need, stash the size in the first int, and return ptr+1 as the pointer to the array. When you need the size, decrement the pointer and peek at the stashed value. Just remember to free the whole block starting from the beginning, and not just the array.

13

  • 20

    I’m sorry for this posting a comment so late but if the compiler does not know what the pointer is pointing to how does free know how much memory to clear? I do know that this information is stored internally for functions like free to use. So my question is why can’ the compiler do so too?

    Mar 3, 2013 at 19:19

  • 17

    @viki.omega9, because free discovers the size at runtime. The compiler can’t know the size because you could make the array a different size depending on runtime factors (command line arguments, contents of a file, phase of moon,etc).

    Mar 3, 2013 at 20:48

  • 20

    Quick follow up, why isn’t there a function that can return the size the way free does?

    Mar 3, 2013 at 22:52

  • 5

    Well, if you could guarantee that the function was only called with malloced memory and the library tracks the malloced memory the way most I’ve seen do (by using an int before the returned pointer) then you could write one. But if the pointer is to a static array or the like, it would fail. Similarly, there is no guarantee that the size of malloced memory is accessible to your program.

    Mar 3, 2013 at 23:11

  • 13

    @viki.omega9: Another thing to keep in mind is that the size recorded by the malloc/free system may not be the size you asked for. You malloc 9 bytes and get 16. Malloc 3K bytes and get 4K. Or similar situations.

    – Zan Lynx

    Jul 20, 2014 at 3:48

110

The answer is, “No.”

What C programmers do is store the size of the array somewhere. It can be part of a structure, or the programmer can cheat a bit and malloc() more memory than requested in order to store a length value before the start of the array.

3

  • 3

    Thats how pascal strings are implemented

    – dsm

    Jan 29, 2009 at 16:44

  • 8

    and apparently pascal strings are why excel runs so fast!

    Jul 14, 2010 at 19:48

  • 8

    @Adam: It is fast. I use it in a list of strings implementation of mine. It is super-fast to linear search because it is: load size, prefetch pos+size, compare size to search size, if equal strncmp, move to next string, repeat. It’s faster than binary search up to about 500 strings.

    – Zan Lynx

    Jul 14, 2010 at 19:52


53

For dynamic arrays (malloc or C++ new) you need to store the size of the array as mentioned by others or perhaps build an array manager structure which handles add, remove, count, etc. Unfortunately C doesn’t do this nearly as well as C++ since you basically have to build it for each different array type you are storing which is cumbersome if you have multiple types of arrays that you need to manage.

For static arrays, such as the one in your example, there is a common macro used to get the size, but it is not recommended as it does not check if the parameter is really a static array. The macro is used in real code though, e.g. in the Linux kernel headers although it may be slightly different than the one below:

#if !defined(ARRAY_SIZE)
    #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0]))
#endif

int main()
{
    int days[] = {1,2,3,4,5};
    int *ptr = days;
    printf("%u\n", ARRAY_SIZE(days));
    printf("%u\n", sizeof(ptr));
    return 0;
}

You can google for reasons to be wary of macros like this. Be careful.

If possible, the C++ stdlib such as vector which is much safer and easier to use.

11

  • 13

    ARRAY_SIZE is a common paradigm used by practical programmers everywhere.

    – Sanjaya R

    Jan 29, 2009 at 17:19

  • 6

    Yes it is a common paradigm. You still need to use it cautiously though as it is easy to forget and use it on a dynamic array.

    – Ryan

    Jan 29, 2009 at 17:27

  • 2

    Yes, good point, but the question being asked was about the pointer one, not the static array one.

    Jan 29, 2009 at 17:40

  • 2

    That ARRAY_SIZE macro always works if its argument is an array (i.e. expression of array type). For your so-called “dynamic array”, you never get an actual “array” (expression of array type). (Of course, you can’t, since array types include their size at compile-time.) You just get a pointer to the first element. Your objection “does not check if the parameter is really a static array” is not really valid, since they are different as one is an array and the other isn’t.

    – newacct

    Feb 28, 2013 at 18:52


  • 3

    There is a template function floating around that does the same thing but will prevent the use of pointers.

    Apr 23, 2013 at 2:24