54
char str[] = "beautiful earth";
memset(str, '*', 6);
printf("%s", str);

Output:
******ful earth

Like the above use of memset, can we initialize only a few integer array index values to 1 as given below?

int arr[15];
memset(arr, 1, 6);
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user1762571
  • 1,888
  • 7
  • 28
  • 47
  • 3
    possible duplicate of [memset integer array?](http://stackoverflow.com/questions/7202411/memset-integer-array) – 000 Jun 25 '13 at 03:52
  • 4
    Nope. `memset()` casts down to a byte and dupes it across the region. – Mysticial Jun 25 '13 at 03:53
  • 1
    You could always read the memset documentation to find out what it does. – Jim Balter Jun 25 '13 at 05:51
  • 1
    @JoeFrambach The accepted answer to that question doesn't apply here. – Jim Balter Jun 25 '13 at 05:53
  • Possible duplicate of [Why does "memset(arr, -1, sizeof(arr)/sizeof(int))" not clear an integer array to -1?](https://stackoverflow.com/questions/7202411/why-does-memsetarr-1-sizeofarr-sizeofint-not-clear-an-integer-array-t) – Andrik007 Oct 13 '19 at 17:50

10 Answers10

86

No, you cannot use memset() like this. The manpage says (emphasis mine):

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

Since an int is usually 4 bytes, this won't cut it.


If you (incorrectly!!) try to do this:

int arr[15];
memset(arr, 1, 6*sizeof(int));    //wrong!

then the first 6 ints in the array will actually be set to 0x01010101 = 16843009.

The only time it's ever really acceptable to write over a "blob" of data with non-byte datatype(s), is memset(thing, 0, sizeof(thing)); to "zero-out" the whole struture/array. This works because NULL, 0x00000000, 0.0, are all completely zeros.


The solution is to use a for loop and set it yourself:

int arr[15];
int i;

for (i=0; i<6; ++i)    // Set the first 6 elements in the array
    arr[i] = 1;        // to the value 1.
Jonathon Reinhart
  • 132,704
  • 33
  • 254
  • 328
  • In my system size of int is 4 bytes. So i tried memset(arr,1,8). But it is initializing the whole array with that 4 byte value instead of filling only first 8 bytes as per my third argument. – user1762571 Jun 25 '13 at 03:58
  • 1
    I would be more convinced by your claim memset did this if you start out by initializing the whole array to 0 (using int arr[15] = {0}) and then doing the memset(arr, 1, 8); And if you still have an array full of 0x01010101's after that, you have a buggy c runtime :-). – Mike Woolf Jun 25 '13 at 04:06
  • @Jonathon, I agree it's the wrong thing to do, but the claim is that memset is behaving in a way radically different from what it's supposed to do. I pointed out that probably is not the case and described a way to really check it. – Mike Woolf Jun 25 '13 at 04:18
  • 1
    @MikeWoolf Right. My comment was directed to the OP. Certainly he is free to code whatever he wishes, but if he's hoping to somehow *trick* memset into initializing his array, it's going to end poorly. – Jonathon Reinhart Jun 25 '13 at 04:31
  • "NULL, 0x00000000, 0.0, are all completely zeros." -- NULL is not necessarily all (or any) 0 bits. – Jim Balter Jun 25 '13 at 05:59
  • @JimBalter While you are technically correct, I would be curious to know of any platforms where `NULL` is non-zero. – Jonathon Reinhart Apr 17 '14 at 00:28
  • off-topic question, I thought memset works on pointers, arr is not a pointer. – briankip Mar 20 '16 at 15:08
  • 2
    @briankip The array [decays to a pointer](http://stackoverflow.com/questions/1461432/what-is-array-decaying) here. The `&` is optional in this case; `memset(&arr, ...)` would do the same thing. – Jonathon Reinhart Mar 20 '16 at 15:57
  • 1
    @JonathonReinhart Dangerous wording (*'& is optional'*). Both variants work, as memset accepts `void*`, but pointer type is different: `arr` decays to `int*` whereas `&arr` gives a pointer of type `int(*)[15]`! – Aconcagua Oct 23 '18 at 13:03
  • 1
    @Jacqueline P. If you think this answer is incorrect, the right thing to do is leave a comment, not suggest an edit. That way I can explain why your understanding isn't quite right. – Jonathon Reinhart Mar 11 '20 at 05:26
  • @JonathonReinhart I'm wondering why you don't take the value of `Binary` but take the number of `hexadecimal 16843009 = 0x01010101`? – Oosutsuke Sep 06 '21 at 21:08
  • An `int` is usually 4 bytes. In that example, *each byte* would be set to the value 1 (0x01). So when you consider the 4-byte integer, its value (regardless of endianness) would be 0x01010101. Perhaps the question should be turned around: why would you consider binary, or octal, or any other base? – Jonathon Reinhart Sep 06 '21 at 23:44
26

Short answer, NO.

Long answer, memset sets bytes and works for characters because they are single bytes, but integers are not.

vidit
  • 6,293
  • 3
  • 32
  • 50
7

On Linux, OSX and other UNIX like operating systems where wchar_t is 32 bits and you can use wmemset() instead of memset().

#include<wchar.h>
...
int arr[15];
wmemset( arr, 1, 6 );

Note that wchar_t on MS-Windows is 16 bits so this trick may not work.

ceilingcat
  • 671
  • 7
  • 11
5

The third argument of memset is byte size. So you should set total byte size of arr[15]

memset(arr, 1, sizeof(arr));

However probably, you should want to set value 1 to whole elements in arr. Then you've better to set in the loop.

for (i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) {
    arr[i] = 1;
}

Because memset() set 1 in each bytes. So it's not your expected.

mattn
  • 7,571
  • 30
  • 54
  • But in my system size of int is 4 bytes. So i tried memset(arr,1,8). But it is initializing the whole array with that 4 byte value instead of filling only first 8 bytes as per my third argument – user1762571 Jun 25 '13 at 04:03
  • You must not use constant value 8, you've better to use count of element size. for example `n * sizeof(int)`. – mattn Jun 25 '13 at 04:09
  • 2
    When calling `memset(arr, 1, 4)`, it become 0x01 0x01 0x01 0x01. But your expected is `0x00 0x00 0x00 0x01`. (This is depend on your CPU archtecture). – mattn Jun 25 '13 at 04:10
  • got it. thanks. I tried memset(arr,1,2*sizeof(int)); as you said but still it is initializing the whole array with same value. – user1762571 Jun 25 '13 at 04:14
  • As I wrote in above, you shouldn't use memset if you want to set value 1 each elements (not set 1 each bytes). – mattn Jun 25 '13 at 04:15
  • @user1762571 " it is initializing the whole array with that 4 byte value instead of filling only first 8 bytes as per my third argument " -- no, it's only setting 8 bytes. You're misinterpreting the results somehow or you're copying the initial bytes to the rest of the array. – Jim Balter Jun 25 '13 at 06:01
4

Since nobody mentioned it...

Although you cannot initialize the integers with value 1 using memset, you can initialize them with value -1 and simply change your logic to work with negative values instead.

For example, to initialize the first 6 numbers of your array with -1, you would do

memset(arr,-1,6*(sizeof int));

Furthermore, if you only need to do this initialization once, you can actually declare the array to start with values 1 from compile time.

int arr[15] = {1,1,1,1,1,1};
i Code 4 Food
  • 2,144
  • 1
  • 15
  • 21
3

Actually it is possible with memset_pattern4 which sets 4 bytes at a time.

memset_pattern4(your_array, your_number, sizeof(your_array));
Troy
  • 690
  • 1
  • 7
  • 25
jjosephi
  • 31
  • 1
2

No, you can't [portably] use memset for that purpose, unless the desired target value is 0. memset treats the target memory region as an array of bytes, not an array of ints.

A fairly popular hack for filling a memory region with a repetitive pattern is actually based on memcpy. It critically relies on the expectation that memcpy copies data in forward direction

int arr[15];

arr[0] = 1;
memcpy(&arr[1], &arr[0], sizeof arr - sizeof *arr);

This is, of course, a pretty ugly hack, since the behavior of standard memcpy is undefined when the source and destination memory regions overlap. You can write your own version of memcpy though, making sure it copies data in forward direction, and use in the above fashion. But it is not really worth it. Just use a simple cycle to set the elements of your array to the desired value.

AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • memcpy copies multiple bytes in one iteration for optimization so I don't think this trick can actually work on strings larger than 8 chars at least – Fayeure Mar 03 '23 at 22:47
0

Memset sets values for data types having 1 byte but integers have 4 bytes or more , so it won't work and you'll get garbage values. It's mostly used when you are working with char and string types.

0

The following program shows that we can initialize the array using memset() with -1 and 0 only

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

void printArray(int arr[], int len)
{
        int i=0;
    for(i=0; i<len; i++)
    {
        printf("%d ", arr[i]);
    }
    puts("");
}

int main()
{
    int arrLen = 15;
    int totalNoOfElementsToBeInitialized = 6;

    int arr[arrLen];
    printArray(arr, arrLen);
    memset(arr, -1, totalNoOfElementsToBeInitialized*sizeof(arr[0]));
    printArray(arr, arrLen);
    memset(arr, 0, totalNoOfElementsToBeInitialized*sizeof(arr[0]));
    printArray(arr, arrLen);
    memset(arr, 1, totalNoOfElementsToBeInitialized*sizeof(arr[0]));
    printArray(arr, arrLen);
    memset(arr, 2, totalNoOfElementsToBeInitialized*sizeof(arr[0]));
    printArray(arr, arrLen);
    memset(arr, -2, totalNoOfElementsToBeInitialized*sizeof(arr[0]));
    printArray(arr, arrLen);
    return 0;
}
ganjaam
  • 1,030
  • 3
  • 17
  • 29
0

Ideally you can not use memset to set your arrary to all 1.
Because memset works on byte and set every byte to 1.

memset(hash, 1, cnt);

So once read, the value it will show 16843009 = 0x01010101 = 1000000010000000100000001
Not 0x00000001
But if your requiremnt is only for bool or binary value then we can set using C99 standard for C library

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>        //Use C99 standard for C language which supports bool variables

int main()
{
    int i, cnt = 5;
    bool *hash = NULL;
    hash = malloc(cnt);

    memset(hash, 1, cnt);
    printf("Hello, World!\n");

    for(i=0; i<cnt; i++)
        printf("%d ", hash[i]);

    return 0;
}

Output:

Hello, World!
1 1 1 1 1

akD
  • 1,137
  • 1
  • 10
  • 15