61
votes

The manpage says about memset:

#include <string.h>
void *memset(void *s, int c, size_t n)

The memset() function fills the first n bytes of the memory area pointed to by s with the constant byte c.

It is obvious that memset can't be used to initialize int array as shown below:

int a[10];
memset(a, 1, sizeof(a));  

it is because int is represented by 4 bytes (say) and one can not get the desired value for the integers in array a.
But I often see the programmers use memset to set the int array elements to either 0 or -1.

int a[10];
int b[10];
memset(a, 0, sizeof(a));  
memset(b, -1, sizeof(b));  

As per my understanding, initializing with integer 0 is OK because 0 can be represented in 1 byte (may be I am wrong in this context). But how is it possible to initialize b with -1 (a 4 bytes value)?

2
Downvoter, care to explain? Is that question irrelevant for this site or something else?haccks
You are slightly wrong about the reason initializing with 0 is OK. It is OK because 0 fits in an unsigned char (so it is not truncated when used as the second argument to memset) and because the bit pattern in memory for a sizeof(int)-byte zero is identical to the bit pattern in memory for sizeof(int) sequential one-byte zeros. Both of those things must be true for this to work. In fact, those things are true for exactly two numbers in twos-complement arithmetic: 0 and -1.zwol
@zwol: Hmm? The first sentence speaks of zeros and so is not literally true for −1. So presumably you intend to implicitly parameterize the first sentence: It works for x if the bits for an int with value x are the same as the bits for sizeof(int) unsigned char each with the value x. Further, we must consider the unsigned char with value x as resulting from conversion of x to unsigned char, as −1 is not representable. If so, then it is not true that 0 and −1 are the only such values. 16,843,009 • x works for any integer 0 ≤ x < 256. (16,843,009 is hex 1010101).Eric Postpischil
@zwol: Except for the fact that C does not require the bit positions in integers of different widths to represent the same values.Eric Postpischil
@EricPostpischil I don't understand your example. No multiple of 16,843,009 is representable by any of the char types (well, unless you're on a machine where CHAR_BIT >= 25.)zwol

2 Answers

69
votes

Oddly, the reason this works with -1 is exactly the same as the reason that this works with zeros: in two's complement binary representation, -1 has 1s in all its bits, regardless of the size of the integer, so filling in a region with bytes filled with all 1s produces a region of -1 signed ints, longs, and shorts on two's complement hardware.

On hardware that differs from two's complement the result will be different. The -1 integer constant would be converted to an unsigned char of all ones, because the standard is specific on how the conversion has to be performed. However, a region of bytes with all their bits set to 1 would be interpreted as integral values in accordance with the rules of the platform. For example, on sign-and-magnitude hardware all elements of your array would contain the smallest negative value of the corresponding type.

5
votes

When all bits of a number are 0, its value is also 0. However, if all bits are 1 the value is -1.

If we write int a[2], 4x2 bytes of memory is allocated which contains random/garbage bits-

00110000 00100101 11100011 11110010    11110101 10001001 00111000 00010001

Then, we write memset(a, 0, sizeof(a)). Now, memset() works byte by byte, and one byte representation (unsigned char) of 0 is 00000000. So, it becomes-

00000000 00000000 00000000 00000000    00000000 00000000 00000000 00000000

Therefore, both a[0] and a[1] are initialized with 0.


Now, lets see memset(a, -1, sizeof(a)): one byte for -1 is 11111111. And, we get-

11111111 11111111 11111111 11111111    11111111 11111111 11111111 11111111

Here, both a[0] and a[1] will have the value -1.


However, for memset(a, 1, sizeof(a)): 1 in a byte is 00000001-

00000001 00000001 00000001 00000001    00000001 00000001 00000001 00000001

So, the value will be- 16843009.