More than a third word of the alphabet, C is a strictly compiled programming language that forms the base of all other languages in the programming world today. In other words, the programs written in C run only after being compiled. C is constrained to certain parameters or functions but contains some different functions that serve some specific purpose. In this article, you would be learning about memset() in C and other factors and use cases associated with it.
What is memset()?
The function memset("memory setter") is a standard library function in C language that sets or fills a memory block semantically with a value.
For instance, consider that you have an array of 8 characters consuming 8 bytes of memory when this array is declared, your computer chunks off 8 bytes of memory on the heap available in your system. This memory allocation is not random. Randomization occurs only when the process like Address Space Layout Randomization occurs for some exemplary purposes or, hexadecimal allocation of address in the range of 0x00 to 0x07. Consider you declare an array of array of 8 characters as shown.
Initially, you are completely unaware of the contents of this block memory taken by the array without initializing the array. Although it can be nothing but can be an old value that you might have used in the previous programs, or the block in the memory might be undefined.
In general, and to keep up with good practices while working with C, it is best to gain full control over any memory used in any given program. Therefore, instead of leaving these 8 bytes of memory vacant, you must always set or fill the memory with a known or given value along with a null byte (\0). In this way, you can ensure full control of the memory block consumed by the array defined by you. See the image below to get a visual of what is being discussed.
In other words, all you want is to memset the functional blocks of memory. The memset() takes the following parameters. The function accepts three parameters, a pointer to the block of memory and an integer followed by a size_t which is nothing but an unsigned integer variable designed to hold any index of an array.
The first parameter represents a pointer of type void since the memory block is initially empty or about to be filled. The type void signifies the pointer can reference the memory regardless of type.
The second parameter is the integer to fill with the pointer allocation. Note that this parameter is received as an integer argument that later gets converted to the character when memory filling is required. This conversion ensures that functions keep only 8 bits needed from the integer parameter. Else it might consume more memory than needed.
The third parameter represents the given size of the memory block that has to be filled. When the pointer references the memory location to fill this space, it tells nothing about how much memory it should fill. Therefore, the main purpose of passing this parameter is to ensure proper and positive size so that memory allocation doesn't suffer memory loss.
Return value of memset()
The default return value of memset() is void * (pointer with no return type). You might receive nothing back from the memset() if you expect to get what you gave to these functions. You might only expect to get some output after the function turns around and returns a pointer with the same memory address passed when you try to call the memset function.
How to use memset()?
To use memset() in your program, the first thing you need to do is to include the string header file in your program, as shown below.
Once the string library of C is included in your program, you need nothing more. You can easily access the memset function directly. To make it clearer and easy, consider the below code snippet containing two other libraries like <stdio.h> and <stdlib.h> (for the usage of exit and printf purposes).
When is memset() used?
As previously discussed, while programming in C, it is always a best practice to have tight control and maintenance of memory while allocating memory and initializing it. In case you don't initialize immediately, other dedicated functions like strcpy might come into use. Proper usage of strcpy involves a new block memory allocation method where a copy of a string is kept aside before actually using it. Since it is not initialized, it might need to be declared first before actually using strcpy. In such cases, memset() is very suitable to fill the block or clear them out initially. Consider the example given below to understand why is memset() used.
In general, memset() is a great tool to be considered while working with C and memory allocation methods. In simple words, if you can't initialize it, memset it.
Applications of memset()
So far, you have to see all the relevant examples and use cases for a particular memset() instance. But, to understand better, you need to look at multiple examples that will be discussed as an application of memset. Consider the below examples that describes its applications.
a = Hello from JournalDev Filling the first five characters a with 'H' using memset After memset, a = HHHHH from JournalDev
It is quite clear from the previous as well as this example how memset() handles initialization. In the code given above, you can see how memset acts with the variable defining the size of the character array or string. After using the memset() function, you see five repeated characters of H from the given string.
a = Hello from JournalDev Filling the last five characters a with 'H' using memset After memset, a = Hello from JournHHHHH
This example is similar to the previous one with a catchy hook. It is important to understand the variations of the same programs with different usage techniques of memset(). In the above example, you can see that only the offset location is being filled. In this example, the only difference is the last five characters filled with H since you can see that the memory location or initialization of address has already been done.
Memset() vs calloc() vs naive iteration
There are times when you can opt to use memset() to zero for array initialization. Often, there exists some performance issues of other functions like naive approaches or using calloc() function. There are also some speed issues and memory allocation techniques that are hard to understand and implement. To understand how memset solves these kinds of problems, see the below example code to find why memset() is beneficial to use and how both memset() and calloc() can run on a Linux machine using the <time.h> header file.
Time for memset() = 0.000002 seconds Time for calloc() = 0.000005 seconds Time for naive iteration = 0.000006 seconds
In the above example, you can easily observe and understand that memset() is thrice as fast as both the native iteration and calloc(). It is so fast because it is already optimized based on the architecture provided by the C compiler, the speed is automatically enhanced.
As popularly said, when you don't initialize, memset it. This proverb usually talks about the advantage of memset over other approaches like calloc() or native iteration. In this article, you saw how to deal with such issues while initializing an array when the space is vacant or unused. The problems and solutions you find in this article tell you how memset can be an important aspect while dealing with memory allocation with a programming language like C.