4

I am writing host code for a CUDA program, so I am stuck using standard C functions. I am having a problem with initializing the elements of an integer array using the memset function. I was under the impression you could use memset to initialize an integer array to, for example, all 4s like this:

int num_elements = 10;
int* array_example = (int*)malloc(num_elements * sizeof(int));
memset(array_example, 4, sizeof(array_example));

But when I do this, it sets each byte, not each int, to 4. If I say:

memset(array_example, 4, 1);

I get a 4 in the first integer and if I say:

memset(array_example, 4, 2);

I get 1024 in the first integer and 0 in the second. I understand the memset function sets the number of bytes specified in the third parameter to 4, but is there any way to use memset to set each integer to 4 instead of each byte? Otherwise, am I stuck using a for loop? My GPU has a low compute capability so I don't have access to some of the nicer CUDA additions that allow more C++ usage.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
Blake
  • 75
  • 1
  • 2
  • 10

4 Answers4

4

If you know the size of a table and want to set each element to the certain value you can always write:

int array[10] = { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 };

If you use gcc you can also do this in this way:

int array[10] = {[0 ... 9] = 4};

When you have to dynamically allocate the array I doubt that there is any alternative solution then just using a simple loop.

Adam Sznajder
  • 9,108
  • 4
  • 39
  • 60
4

Just though I'd add an option and contribute a few points:

  1. If you're working in C++ rather than C, try using std::fill(), which is generic - and let the compiler worry about the optimization:

     std::fill_n(my_array, array_length, constant_value);
    
  2. The signature of memset() is:

     void *memset(void *s, int c, size_t n);
    

    while it supposedly takes an int, it actually expects a(n unsigned) byte value (i.e. between 0 and 0xFF).

  3. Continuing tool's answer - some useful memset'ing you can do which amounts to using (unsigned) ints is setting arrays to either 0 or to UINT_MAX, i.e. to 0xFFFF or 0xFFFFFFFF etc. depending on sizeof(unsigned).

  4. If we had strided memset(), you could apply four of these to get 4-byte ints set into an array. However, we don't, and in fact it seems there's currently no advantage to doing that over just looping.

einpoklum
  • 118,144
  • 57
  • 340
  • 684
3

memset may be used successfully (not question of lucky) in case the bits representing the value of the int have a pattern which is byte-per-byte constant, considering the representation of the int itself (e.g. 2-complement).

E.g., if you memset the array with 4, it turns out that each int is initialized with 0x04040404 (considering sizeof(int)=32), which may be ok or not depending on your needs.

This applies for a number of specific values of the initialization value for the integer.

But this results in barely portable code.

It should always work if you are going to initialize each int at zero.

tool
  • 31
  • 1
2

There is no standard alternative to memset that write integers. You'll have to write a loop.

Wim Yedema
  • 21
  • 1
  • OK, thanks. I inherited a 5000+ line program for my research in medical imaging and they used `memset` all over the place as if it could init each integer. Their code works so I was trying to figure out if I was missing something or they had luckily written over the garbage initialization. – Blake Jun 21 '12 at 09:23