memset() in C

Filed Under: C Programming
Using Memset In C

The memset() function in C is used to set blocks of memory with a particular value.

In this article, we’ll have a look at how we can use this function in C programs.


Syntax of memset() in C

This function takes a memory location, taken to be a void* pointer. It then copies a byte (character) to the first n bytes pointed to by the memory location.

Since it updates the memory location, it also returns a pointer to that updated memory location, which is again a void* pointer.

Therefore, we can write its prototype as:

void* memset(void* mem_loc, int c, size_t n);

Here, mem_loc is the relevant memory location, and c is the unsigned character. It sets the first n bytes of mem_loc.

Relevant Header Files

Since this deals with characters and therefore strings (char*), we get this function in the <string.h> header.

We will now write the complete import and the function call.

#include <string.h>

void* memset(void* mem_loc, int c, size_t n);

Let’s now look at examples regarding how we can use this function.

Using the memset() function in C

#include <stdio.h>
#include <string.h>

int main() {
    char a[] = {"Hello from JournalDev"};

    printf("a = %s\n", a);
    
    printf("Filling the first 5 characters a with 'H' using memset\n");
    
    memset(a, 'H', 5 * sizeof(char));
    
    printf("After memset, a = %s\n", a);

    return 0;
}

The above code snippet fills the first 5 characters of the string “Hello from JournalDev” with ‘H’. Let’s take a look at the output now:

a = Hello from JournalDev
Filling the first 5 characters a with 'H' using memset
After memset, a = HHHHH from JournalDev

As you can observe, the first 5 locations are indeed filled with ‘H’.

Now let’s take another example, where you want to fill elements from an offset location.

#include <stdio.h>
#include <string.h>

int main() {
    char a[] = {"Hello from JournalDev"};

    printf("a = %s\n", a);
    
    printf("Filling the last 5 characters a with 'H' using memset\n");
    
    size_t a_len = strlen(a);
    
    //Using an offset of (a + a_len - 5), so that we can
    //fill the last 5 characters
    memset(a + (a_len - 5), 'H', 5 * sizeof(char));
    
    printf("After memset, a = %s\n", a);

    return 0;
}

Output

a = Hello from JournalDev
Filling the last 5 characters a with 'H' using memset
After memset, a = Hello from JournHHHHH

This time, the last five characters are filled with ‘H’, since we specified the starting memory location address appropriately.


memset() vs calloc() vs naive iteration

A lot of times, we can use memset() to zero initialize arrays. Often, the performance of memset() is much faster than similar methods like calloc().

The below example illustrates this point while comparing the running time of both memset() and calloc() on a Linux Machine, using the <time.h> header file.

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

void* init_with_memset(int* arr, size_t num_locations) {
    // Perform zero initialization with memset
    // on an integer array
    return memset(arr, 0, num_locations * sizeof(int)); 
}

void* init_with_calloc(int* arr, size_t num_locations) {
    arr = calloc(num_locations, sizeof(int));
    return arr;
}

void* init_with_iteration(int* arr, size_t num_locations) {
    // Naive unoptimized iteration using array indexing
    for (int i=0; i<num_locations; i++) {
        arr[i] = 0;
    }
    return arr;
}

int main() {
    // Set the array to -1 initially
    int arr[2560];
    for (int i=0; i<2560; i++)
        arr[i] = -1;

    clock_t start_time, end_time;
    double total_time;

    start_time = clock();
    // 1000 locations
    init_with_memset(arr, 1000);
    end_time = clock();
    total_time  =  (double) (end_time - start_time);
    total_time =   total_time / CLOCKS_PER_SEC;
    printf("Time for memset() = %.6f seconds\n", total_time);
    
    start_time = clock();
    // 1000 locations
    init_with_calloc(arr, 1000);
    end_time = clock();
    total_time  =  (double) (end_time - start_time);
    total_time =   total_time / CLOCKS_PER_SEC;
    printf("Time for calloc() = %.6f seconds\n", total_time);
    
    start_time = clock();
    // 1000 locations
    init_with_iteration(arr, 1000);
    end_time = clock();
    total_time  =  (double) (end_time - start_time);
    total_time =   total_time / CLOCKS_PER_SEC;
    printf("Time for naive iteration = %.6f seconds\n", total_time);

    return 0;
}

Output

Time for memset() = 0.000002 seconds
Time for calloc() = 0.000005 seconds
Time for naive iteration = 0.000006 seconds

As you can observe, memset() is almost thrice as fast as both calloc() and naive iteration, since it is optimized based on the architecture, beyond the C compiler!


Conclusion

We learned about how we can use memset() to set values of a memory location. We also verified that the performance of memset() is much better than the other functions since it is optimized as per the architecture.

References


Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages