Question

It is more than a funny question. :-)

I wish to initialize an array in C, but instead of zeroing out the array with calloc. I want to set all element to one. Is there a single function that does just that?

I have used my question above to search in google, no answer. Hope you can help me out! FYI, I am first year CS student just starting to program in C.

Was it helpful?

Solution

There isn't a standard C memory allocation function that allows you to specify a value other than 0 that the allocated memory is initialized to.

You could easily enough write a cover function to do the job:

void *set_alloc(size_t nbytes, char value)
{
    void *space = malloc(nbytes);
    if (space != 0)
        memset(space, value, nbytes);
    return space;
}

Note that this assumes you want to set each byte to the same value. If you have a more complex initialization requirement, you'll need a more complex function. For example:

void *set_alloc2(size_t nelems, size_t elemsize, void *initializer)
{
    void *space = malloc(nelems * elemsize);
    if (space != 0)
    {
        for (size_t i = 0; i < nelems; i++)
            memmove((char *)space + i * elemsize, initializer, elemsize);
    }
    return space;
}

Example usage:

struct Anonymous
{
    double d;
    int    i;
    short  s;
    char   t[2];
};

struct Anonymous a = { 3.14159, 23, -19, "A" };

struct Anonymous *b = set_alloc2(20, sizeof(struct Anonymous), &a);

OTHER TIPS

memset is there for you:

memset(array, value, length);

There is no such function. You can implement it yourself with a combination of malloc() and either memset() (for character data) or a for loop (for other integer data).

The impetus for the calloc() function's existence (vs. malloc() + memset()) is that it can be a nice performance optimization in some cases. If you're allocating a lot of data, the OS might be able to give you a range of virtual addresses that are already initialized to zero, which saves you the extra cost of manually writing out 0's into that memory range. This can be a large performance gain because you don't need to page all of those pages in until you actually use them.

Under the hood, calloc() might look something like this:

void *calloc(size_t count, size_t size)
{
    // Error checking omitted for expository purposes
    size_t total_size = count * size;
    if (total_size < SOME_THRESHOLD)  // e.g. the OS's page size (typically 4 KB)
    {
        // For small allocations, allocate from normal malloc pool
        void *mem = malloc(total_size);
        memset(mem, 0, total_size);
        return mem;
    }
    else
    {
        // For large allocations, allocate directory from the OS, already zeroed (!)
        return mmap(NULL, total_size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0);
        // Or on Windows, use VirtualAlloc()
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top