1

I have a macro for calculating array sizes in my C code:

#define sizearray(a)  (sizeof(a) / sizeof((a)[0]))

When I test it, it works fine for statically defined arrays, but not so for dynamically defined arrays (see below). Not sure I understand why this is the case. Is there any way of calculating the size of an array allocated on the heap?

/* test sizearray macro */
void testSIZEARRAY(void)
{
    /* test case for statically defined array */
    int a[5] = {0,0,0,0,0};

    assert(sizearray(a) == 5);

    /* test case for dynamically defined array */
    int *b;

    b = calloc(5, sizeof(int));

    assert(sizearray(b) == 5);

    free(b);
}
4

4 Answers 4

5

The answer is no, there is no standard way to get the size of a dynamically allocated array.
For all practical purposes, you have to keep track it yourself.

However, there are some compiler-specific methods that do that:

Windows (Visual Studio): _msize()

GCC: msize() Can't find it in the GCC docs...

Sign up to request clarification or add additional context in comments.

4 Comments

You might say that generally speaking there's no way to calculate the size of a dynamically allocated array, you just have to keep track of it.
Does it returns the allocated size or the size which was asked?
@AProgrammer Good question. I'm not sure on that and the docs aren't clear on it.
@AProgrammer It looks like it does return the size that was asked. I just tested it with 1 and 63, sizes that would most certainly have been padded up - and it does return 1 and 63.
4
int *b;
...
assert(sizearray(b) == 5);

A pointer is not an array. b is declared as pointer to int

Here

sizeof b == sizeof (int *)

The sizeof operator applied to an object of a pointer type is the same as the size of the pointer type and is not equivalent to the size of the allocated array.

To know the size of your allocated array object you have to inspect what was allocated. In your example you allocate an object of 5 int, so the size of your array is:

 5 * sizeof (int)

(or equivalent, 5 * sizeof *b)

Comments

3

There is no way to calculate the size of an array if you only have a pointer to its first element (as you do in the above case with int *b). You need to either store the array size separately and use it together with your pointer, or somehow mark the end of the array. The latter solution is used in character arrays, which are usually null-terminated (have \0 as their last character). In this case, you can calculate the size by looping till you encounter such a termination character.

Comments

1

The followng is bad advice, do not do that.

To get the memory allocated by the current glibc's malloc() (et al) you could try the following:

#include <stdlib.h>
#include <stdio.h>

#define GLIB_MSIZE_T size_t /* We need to have a four byte unsigned integer type 
                               here. */

#define GLIB_MSIZE(p) \
        *((GLIB_MSIZE_T*) (((char*) p) - sizeof(GLIB_MSIZE_T)))

int main(int iArgC, char ** ppszArgV)
{
        if (1 >= iArgC)
        {
                fprintf(stderr, "usage: %s <bytes to allocate>\n", ppszArgV[0]);
                return EXIT_FAILURE;
        }

        {
                /* This conversion uing 'atol()' only works up until to a certain size
                   of the integer represented by 'ppszArgV[1]'. */
                size_t size = atol(ppszArgV[1]);

                void * pv = malloc(size);
                if (!pv)
                {
                        fprintf(stderr, "Allocation of %u bytes failed.\n", size);
                        return EXIT_FAILURE;
                }

                printf("Asked for %u bytes, got %u bytes.\n", size, GLIB_MSIZE(pv));
        }

        return EXIT_SUCCESS;
}

Besides the fact one indeed could get the amount of memory allocated, the interesting thing to see when paying with this code is, that in most of the cases more then the size of memory requested is assigned.

Anyhow, the latter makes it unsafe trying to pull information from this on the exact size originally requested.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.