Why does "memset(arr, -1, sizeof(arr)/sizeof(int))" not clear an integer array to -1?
Solution 1
Just change to memset (arr, -1, sizeof(arr));
Note that for other values than 0 and -1 this would not work since memset sets the byte values for the block of memory that starts at the variable indicated by *ptr
for the following num
bytes.
void * memset ( void * ptr, int value, size_t num );
And since int
is represented on more than one byte, you will not get the desired value for the integers in your array.
Exceptions:
- 0 is an exception since, if you set all the bytes to 0, the value will be zero
- -1 is another exception since, as Patrick highlighted -1 is 0xff (=255) in int8_t and 0xffffffff in int32_t
The reason you got:
arr[0] = -1
arr[1] = 255
arr[2] = 0
arr[3] = 0
arr[4] = 0
Is because, in your case, the length of an int is 4 bytes (32 bit representation), the length of your array in bytes being 20 (=5*4), and you only set 5 bytes to -1 (=255) instead of 20.
Solution 2
Don't use memset
to initialize anything else than single-byte data types.
At first sight, it might appear that it should work for initializing an int
to 0
or -1
(and on many systems it will work), but then you're not taking into account the possibility that you might generate a trap representation, causing undefined behavior, or the fact that the integer representation is not necessarily two's complement.
The correct way to initialize an array of int
to -1
, is to loop over the array, and set each value explicitly.
Solution 3
gcc provides a good array initialization shortcut
int arr[32] = {[0 ... 10] = 3, [11 ... 31] = 4}
mind the space before and after ...
Solution 4
Why the division?
memset(arr, -1, sizeof(arr));
Your version, sizeof(arr)/sizeof(int)
, gives you the number of elements in the array.
Solution 5
You can save yourself some typing by initializing the array directly:
int arr[5] = {-1, -1, -1, -1, -1};
That line is shorter than the memset, and it also works.
Ravi Gupta
Updated on July 09, 2022Comments
-
Ravi Gupta almost 2 years
Is it not possible to use
memset
on an array of integers? I tried the followingmemset
call and didn't get the correct integer values in theint
array.int arr[5]; memset (arr, -1, sizeof(arr)/sizeof(int));
Values I got are:
arr[0] = -1 arr[1] = 255 arr[2] = 0 arr[3] = 0 arr[4] = 0
-
Thomas Dignan over 12 yearsmight be easier to do this: int arr[5] = {-1};
-
tinman over 12 years@Tom Dignan: Except that only initialises the first element to -1 and all the rest to 0.
-
-
Patrick B. over 12 yearsWell, in this particular case (for -1 as a value) memset actually works. Because -1 is 0xff in int8_t and 0xffffffff in int32_t and so on. IOW: memset works fine for 0 and -1 but is not very useful for all other cases.
-
Jeff Mercado over 12 yearsNote that
memset()
sets the value of the bytes at the addressed location, not how many "items." You'd want to set the 5 ints worth of bytes to-1
. Doing so will just happen to set the int values to-1
as a coincidence of the format. -
Ioan Paul Pirau over 12 yearsYou are right Patrick, Thank you.. I changed my answer accordingly
-
Sander De Dycker over 12 years@Patrick B. : it will work fine on many platforms, but not all. Not all platforms use two's complement, and you might also trigger trap representations by using
memset
to initialize anint
. -
Rudy Velthuis over 12 years@Jeff: indeed, coincidence, because an int of -1 is usually $FFFFFFFF (assuming 32 bit int and two's complement) and a byte of -1 is $FF. Had he chosen -2 ($FE), it would have become $FEFEFEFE, which is an int of -16843010.
-
Pascal Cuoq over 12 yearsI think this answer should be pondered by a clause such as "Don't use
memset()
... if you want to write absolutely portable code". Most people neither write nor intend to write portable code. Most people call code "portable" when it works for two architectures. The word "correct" in "The correct way ..." could also be changed to "portable". If you're not trying to write absolutely portable code, it's neither more nor less correct. -
Adam Naylor over 12 years+1 @Complicatedseebio couldn't agree more, far too many programmers jump down peoples throats with things like 'correct', and 'stl this'. Far too often they over look what's needed by the specific problem.
-
Sander De Dycker over 12 years@Complicated see bio @Adam : The thing is though, that initializing an array of
int
using a loop is guaranteed to work in all cases, whereas usingmemset
might fail to do it properly (or worse might appear to work). I won't say you can't usememset
if you have intimate knowledge of the platforms the code will run on, and know it won't cause an issue. But I don't have such knowledge about the platforms of everyone who might read this answer, so I prefer to play it safe. I hope that balances out some of the "extremes" (for argument sake) I used in my answer. -
Martin Konicek over 11 years+1 for array initializer, although it's useful just for few values.
-
capitano666 over 10 yearsUpvote for Sander, I didn't understand why the -1 wasn't working for me until I realized the machine I was working with wasn't 2-complement.
-
phuclv over 10 yearsevery int whose all four bytes have the same value can use memset, not only 0 and -1
-
Ciro Santilli OurBigBook.com about 8 years@LưuVĩnhPhúc but are the representations besides 0 guaranteed? stackoverflow.com/q/11138188/895245 says yes for 0, but I think not for others because we don't know where the padding and sign bits are inside each int.
-
Frederick over 7 years@capitano666 - just curious - what processor ("machine") were you using?
-
supercat over 7 years@SanderDeDycker: If the array is of a type
int*_t
, it data is guaranteed to be stored in two's-complement without padding. As for non-two's-complement machines, I would be very surprised if there exist any conforming C99 implementations that are used to run production code but don't use two's-complement. Unisys may still be upgrading their compilers, but the manual I read didn't list any unsigned type longer than 36 bits. -
Sander De Dycker over 7 years@supercat : whether there are 0 or 1000 such implementations that are currently in use, does not change my point of view. I don't know how many there are, nor do I know whether readers of my answer use such implementations (archaic or otherwise), nor do I know whether such implementations might make a comeback in the future. All I know is that my recommendation will work on any conforming implementation.
-
supercat over 7 years@SanderDeDycker: Any code which follows the common advice of favoring uint32_t etc. over int, long, etc. will be limited to implementations which store signed versions of the named-size types in two's-complement format (I think the Standard should have allowed implementations to define uint32_t if they have a 32-bit unsigned type with no padding or trap representations, without regard for whether they have a corresponding two's-complement signed type, but the Standard forbids that). I do not think there is value in adding any complexity to code for purposes of supporting...
-
supercat over 7 years...implementations that do not exist and are extremely unlikely to exist in future.
-
capitano666 over 7 years@Frederick, I'm afraid I don't remember what I was working with 3 years ago, maybe it was a Cubieboard2 [Allwinner sun7i (A20) CPU], but I can't remember for sure.
-
John Z. Li over 6 yearsIMO, besides the portable argument, the problem with "I know this works" is that it hides the programmer's intention, relying on an implicit assumption any reader of that code must know to interpret the code.
-
cmaster - reinstate monica about 4 years
memset()
is ok to initialize complex data types as long as you use it to initialize to zero. You are saying that the correctness ofmemset()
depends on the datatype. But this is simply not the case. You can eithermemset()
a byte buffer to any byte value, or you canmemset()
an object of any type to0
. You only get into trouble when you violate both rules at the same time. -
RobertS supports Monica Cellio about 4 yearsBeside your great hint and to come back to the provided example, there is apparently already undefined behavior since the OP attempt to print indeterminate values.
-
RobertS supports Monica Cellio about 4 yearsOne could also abbreviate that and omit the explicit specification of the amount of elements, since the compiler detects the amount of elements by the number of initializations:
int arr[] = {-1, -1, -1, -1, -1};
. -
RobertS supports Monica Cellio about 4 years"The reason you got: arr[0] = -1 arr[1] = 255 arr[2] = 0 arr[3] = 0 arr[4] = 0 is because..." - Incorrect. You´d forgotten one important thing. Since
arr
is not qualified with eitherstatic
orextern
and is apparently declared inside a function (probablymain()
), the values of the elements ofarr
are indeterminate by definition. Even witharr[1]
you can not be sure which values the remaining bits in the next three bytes are consisted of. Thus, printing the elements ofa[1]
toa[4]
is a clear case of Undefined Behavior. Only ata[0]
you will be able to know the exact result. -
Sander De Dycker about 4 years@cmaster-reinstatemonica : even for initializing to
0
it's not ok. A pointer with all bits set to0
doesn't necessarily represent a null pointer. A floating point with all bits set to0
doesn't necessarily represent0.0
. Before standardization, even integers with all bits set to0
didn't necessarily represent the value0
(due to trap representations, and no exception for all0
bits). Granted, on the vast majority of systems this won't be an issue, but better be safe than sorry. -
cmaster - reinstate monica about 4 years@SanderDeDycker
memset(..., 0, ...)
is just as good/evil ascalloc()
. And you don't advocate against the use ofcalloc()
, do you? -
Sander De Dycker about 4 years@cmaster-reinstatemonica : your assumption is wrong.
-
cmaster - reinstate monica about 4 years@SanderDeDycker At least you are consistent, then :-) Myself, I use both
memset(..., 0, ...)
andcalloc()
where appropriate. But I'm usually working on X86 anyways, no exotic platforms that might implementNULL
with a nonzero bit pattern. I won't doubt that such platforms may exist. Would be quite a braindead platform, though, as C mandates thatNULL
compares equal to0
.