TheUnknownBlog

Back

0. Foreword#

This problem originated from my first programming exam during my freshman year… It was a question involving block decomposition (data chunking), and in my program, I had an operation like this:

memset(mul_tag, 1, sizeof(mul_tag));
cpp

Unsurprisingly, the program resulted in a WA (Wrong Answer). I spent a very, very long time debugging. This line looked completely harmless, didn’t it? But as it turned out, simply changing this line fixed the program! Why??? The answer becomes clear when we look at the memset function prototype.

1. memset Function Introduction#

The prototype for the memset function is as follows:

void *memset(void *s, int c, size_t n);
c
  • s: A pointer to the block of memory to fill.
  • c: The value to be set. Note: Although c is of type int, memset actually converts c to an unsigned char before filling.
  • n: The number of bytes to be set to the value.

The purpose of memset is to set the first n bytes of the memory block pointed to by s to the value specified by c.

2. The Trap#

memset performs its filling operation byte by byte. When a is an int array (assuming int occupies 4 bytes), memset(a, 1, sizeof(a)) will set each byte of each int element to 1. This results in each int element having the value 0x01010101, which is 16843009 in decimal, not the 1 we were hoping for.

3. Exceptions#

Using memset(a, 1, sizeof(a)) is dangerous in most scenarios. However, there are a few exceptional cases where it works as expected or is safe:

  • If a is a char array, memset(a, 1, sizeof(a)) is correct because the char type occupies only one byte.
  • memset(a, 0, sizeof(a)) can be safely used for arrays of any type to initialize the entire array to 0. (This is what we typically do! And it’s precisely why I initially thought memset(a, 1, sizeof(a)) would be fine!)
  • memset(a, -1, sizeof(a)) is safe for int arrays and will correctly initialize the elements to -1. Why? Hint: Computers store negative numbers using two’s complement representation. The two’s complement of -1 (for a 32-bit int) is 11111111 11111111 11111111 11111111, which means every byte is 0xFF. Therefore, memset(a, -1, sizeof(a)) fills every byte with 0xFF, effectively setting each int element to -1.

4. You Should Use std::fill#

Instead of memset for non-zero/non-minus-one initializations (especially in C++), you should use std::fill.

std::fill Example (C++):

#include <algorithm>
#include <array> // Or use raw arrays

std::array<int, 10> a;  // Or: int a[10];
std::fill(a.begin(), a.end(), 1); // Or: std::fill(a, a + 10, 1);
c

std::fill operates on elements of the container or array, assigning the specified value (1 in this case) correctly to each element, regardless of its underlying byte representation.

I'll Never Use memset Again...
https://start-co.de/blog/memset
Author TheUnknownThing
Published at March 10, 2025
Comment seems to stuck. Try to refresh?✨