5
int buff[1000] 
memset(buff, 0, 1000 * sizeof(int));

will initialize buff with o's

But the following will not initialize buff with 5's. So what is the way to achieve this using memset in C (not in C++)? I want to use memset for this purpose.

int buff[1000] 
memset(buff, 5, 1000 * sizeof(int));
user2799508
  • 844
  • 1
  • 15
  • 41
  • What is the type of `buff`? – Barmar Jan 06 '14 at 13:49
  • what is buff datatype, is it integer? – Ishmeet Jan 06 '14 at 13:49
  • 3
    `memset` sets each byte to the specified value. If you're operating on a multi-byte datatype, you can't use `memset` to set them to arbitrary values. – Barmar Jan 06 '14 at 13:51
  • 1
    This isn’t quite a dup of the linked question, as that question is for C++ (where the correct thing to do is to use `std::fill_n`). This question is for C, and the answer is different. – Stephen Canon Jan 06 '14 at 14:06

4 Answers4

9

memset initializes bytes, not data types, to a value. So for your example…

int buff[1000] 
memset(buff, 5, 1000 * sizeof(int));

… if an int is four bytes, all four bytes will be initialized to 5. Each integer will actually have a value of 0x05050505 == 84215045, not 5 as you're expecting.

If you would like to initialize each integer in your array to 5, you'll have to do it like this:

int i;
for(i = 0; i < 1000; i++)
    buff[i] = 5;
Fiddling Bits
  • 8,712
  • 3
  • 28
  • 46
  • 1
    When targeting platforms that have an optimized fill implementation (a la `memset_pattern4` from Paul R’s answer), the compiler may even choose to optimize this loop into a call to that function. – Stephen Canon Jan 06 '14 at 13:57
  • @StephenCanon That's interesting. I've never heard of that before. – Fiddling Bits Jan 06 '14 at 14:00
  • 1
    Compilers definitely perform the optimization when a simple loop can be transformed into e.g. `memcpy` or `memset`. Matching platform-specific functions is less common, but some compilers do implement it. Even if your compiler doesn’t do that, this loop is an excellent candidate for autovectorization. – Stephen Canon Jan 06 '14 at 14:01
1

Depending on what OS you are using you may be able to use memset_pattern4 et al, otherwise you'll just need to do it with a loop.

Paul R
  • 208,748
  • 37
  • 389
  • 560
1

I personally don't recommend memset for general initialization. There are too many things you have to be sure of to be able to correctly and portably use it. It's basically only good for char arrays or microcontroller code.

The way to initialize an array in C is the following (assume size N):

for (i = 0; i < N; ++i)
    buff[i] = init_value;

With C99, you can do more interesting stuff. For example, imagine the buffer is an array of the following struct:

struct something
{
    size_t id;
    int other_value;
};

Then you can initialize like this:

for (i = 0; i < N; ++i)
    buff[i] = (struct something){
        .id = i
    };

This is called designated initializer. Like all other cases of initializers, if you don't mention a specific field of the struct, it will be automatically zero initialized.

Shahbaz
  • 46,337
  • 19
  • 116
  • 182
0

If buff isn't an array of bytes, you can only initialise it to values which consist of repetitive hex values using memset (e.g. -1, 0x01010101, etc)

One way to do this is to use memcpy, thus:

buff[0] = 5;
memcpy(buff + 1, buff, sizeof(buff) - sizeof(*buff))

HOWEVER this relies on undefined behaviour and might or might not work on your system.

A decent compiler should produce an efficient enough loop from

for (i = 0; i < 1000; i++) buff[i] = 5;
Tom Tanner
  • 9,244
  • 3
  • 33
  • 61
  • 1
    I’m not aware of any modern system on which the suggested `memcpy` trick *does* “work”. – Stephen Canon Jan 06 '14 at 13:55
  • 3
    I don't think it's ok to knowingly advise undefined behavior – Shahbaz Jan 06 '14 at 13:55
  • @Shahbaz Depends how his system works and how desparate he is for optimisation. I wouldn't advise memset for filling arrays either, as it's not clear – Tom Tanner Jan 06 '14 at 13:57
  • @TomTanner, a simple for loop that sets the elements can be as optimized as `memcpy`. Note that `memcpy` expects `restrict` pointers to source and destination. That means (roughly speaking) the optimizer can assume they don't overlap and optimize accordingly. If you give it memory regions that overlap, even if your answer is "more optimized", it's simply incorrect. – Shahbaz Jan 06 '14 at 14:01
  • I realise that a decent compiler can produce code as optimised at memset. But believe me I've come across plenty of code like the memcpy, in various places. If the OP is unlucky, they will to. Suppose I should have put this the other way round. – Tom Tanner Jan 06 '14 at 14:04
  • @TomTanner: Then at least use memmove instead – doynax Jan 06 '14 at 14:16
  • @doynax that would do the wrong thing – Tom Tanner Jan 06 '14 at 14:21
  • @doynax: it doesn’t work if you use `memmove`. It depends on `memcpy` not doing an overlap check and copying front-to-back in units of no more than `sizeof(int)` bytes. There used to be some platforms that implemented `memcpy` that way, but I don’t know of any in our modern era. More often than not it’s simply an alias of `memmove`, and when it’s not it usually uses transfers larger than `sizeof(int)` to copy. – Stephen Canon Jan 06 '14 at 14:21
  • @TomTanner: Ah, brain-fart. Sorry. Just plain don't do it then – doynax Jan 06 '14 at 14:24
  • @StephenCanon It works fine on the sun I have in front of me using the not-quite-latest compiler – Tom Tanner Jan 06 '14 at 14:26