Putting the memset() Function to Work

My approach for initializing a buffer is to use a loop and assign each byte a value such as zero or the null character, '\0'. It’s tedious, but necessary. And for the impatient, some functions are available to perform this task for you.

The following code shows how I typically initialize a buffer. This method works and it’s good code, especially for someone like me who is teaching programming and wants to illustrate multiple points:

2021_05_01-Lesson-a.c

#include <stdio.h>

int main()
{
    char buffer[BUFSIZ];
    int x = 0;

    while( x<BUFSIZ )
    {
        buffer[x] = '\0';
        x++;
    }
    puts("Buffer initialized");

    return(0);
}

The while loop at Line 8 plows through character array buffer[], filling each element with the null character byte (Line 10). Simple. Elegant. Refer to last week’s Lesson for info on the defined constant BUFSIZ.

The program outputs the text Buffer initialized, which is accurate but useless.

Another, more direct way to pack a buffer with a given byte value is to use the memset() function. Prototyped in the string.h header file, memset() uses this format:

void *memset(void *b, int c, size_t len);

The function takes three arguments: b for a char buffer, c for the character to pack into the buffer, and len for the buffer’s size. The function returns the first argument, the buffer’s address.

Here is an update to my code, showing how the memset() function makes things tighter:

2021_05_01-Lesson-b.c

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

int main()
{
    char buffer[BUFSIZ];

    memset(buffer, '\0', BUFSIZ);
    puts("Buffer initialized");

    return(0);
}

The while loop from the first example is replaced by a single statement at Line 8:

memset(buffer, '\0', BUFSIZ);

All the pieces are present: The buffer’s address, the character to fill, and the size. These appear in the first listing as well, but sprinkled throughout the code. Variable x is no longer needed. The string.h header file must be included; string functions are essentially memory-manipulation functions in C, which is why memset() is found there.

With the memset() function, you can set any character code value for initializing the buffer. So if you want a buffer filled with the letter A, you set 'A' as the second argument. But when you need to fill a buffer with null characters, you can instead use the handy (yet non-standard) bzero() function. Here is its format:

void bzero(void *s, size_t n);

Argument s is the char buffer to fill with null characters. Argument n is the buffer’s size in bytes. This function is prototyped in the strings.h header file. Many compilers include this header file when you use string.h, though for conformity I specify strings.h directly in the following code:

2021_05_01-Lesson-c.c

#include <stdio.h>
#include <strings.h>

int main()
{
    char buffer[BUFSIZ];

    bzero(buffer, BUFSIZ);
    puts("Buffer initialized");

    return(0);
}

The bzero() function appears at Line 8, replacing memset() from the preceding example. The program’s output is the same, though unlike memset(), bzero() always fills a buffer with null characters.

I find memset() and bzero() to be delightful options for initializing a buffer. Still, I may write my own loops out of habit. Nothing wrong with that.

2 thoughts on “Putting the memset() Function to Work

  1. I have used memset() like this:

    memset(mybuf, 0, sizeof(mybuf)); – for a char array or string where the name represents the address of the buffer, and

    memset(&mystruct, 0, sizeof(mystruct)); – for a structure that requires the “&” operator with the struct name for the address of the struct variable

    I like using the loop approach for portability because it does not depend on memset being in the std lib of the compiler used on whatever platform to which the code is moved. Another advantage of using a loop is for embedded code for a device that requires very small programs due to limited memory, using a loop would not require including the strings.h header. For example, a medical device or an ioT device like a counter, tester, or scanner.

    My example does the same thing as “memset(buffer, ‘\0’, BUFSIZ);” but it lets the “sizeof()” function determine the size of the object being initialized. That way, if buffer size changes or buffer is dynamically created and its size varies depending on some condition, the initialization code always has the correct size without having to manually change the code or add code to set the size when buffer is created. Adding code to set BUFSIZ in those circumstances achieves the same results as using sizeof(), so I am offering the above as another alternative, not better syntax.

Leave a Reply