tags:

views:

383

answers:

3
 u32 iterations = 5;
 u32* ecx = (u32*)malloc(sizeof(u32) * iterations);

 memset(ecx, 0xBAADF00D, sizeof(u32) * iterations);
 printf("%.8X\n", ecx[0]);

 ecx[0] = 0xBAADF00D;
 printf("%.8X\n", ecx[0]);

 free(ecx);

Very simply put, why is my output the following?

0D0D0D0D
BAADF00D

ps: u32 is a simple typedef of unsigned int

edit:

  • Compiling with gcc 4.3.4
  • string.h is included
+9  A: 

The second parameter to memset is typed as an int but is really an unsigned char. 0xBAADF00D converted to an unsigned char (least significant byte) is 0x0D, so memset fills memory with 0x0D.

Tadmas
Oh, that is quite silly. What would be the best approach of going about filling it? Just looping over it manually, or is there a function designed for dealing with larger types than char?
Daniel
Nick D
@Daniel: unless you measure it to be a performance bottleneck, writing a simple loop is the best way to go.
Tadmas
See also http://stackoverflow.com/questions/108866/is-there-memset-that-accepts-integers-larger-than-char
Tadmas
The reason that `memset` takes an `int` even though it really wants an `unsigned char` is that it dates from the days before ANSI C, when function prototypes were introduced. Arguments to unprototyped functions are widened to `int` / `unsigned int`, so to make the prototyped ANSI C definition of `memset` compatible with the old unprototyped definition, it had to take `int`.
caf
+2  A: 

The second argument to memset() is a char not a int or u32. C automatically truncates the 0xBAADF00D int into a 0x0D char and sets each character in memory as requested.

George Phillips
+1  A: 

I tried it with wmemset(). It seems to work:


#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <wchar.h>

int main(void){
  uint32_t iterations = 5;
  uint32_t *ecx = (uint32_t*)malloc(sizeof(uint32_t) * iterations);

  wmemset( (wchar_t*)ecx, 0xBAADF00D, sizeof(uint32_t) * iterations);
  printf("%.8X\n", ecx[0]);

  ecx[0] = 0xBAADF00D;
  printf("%.8X\n", ecx[0]);

  /* Update: filling the array with memcpy() */
  ecx[0] = 0x11223344;
  memcpy( ecx+1, ecx, sizeof(*ecx) * (iterations-1) );
  printf("memcpy:   %.8X %.8X %.8X %.8X %.8X\n",
             ecx[0], ecx[1], ecx[2], ecx[3], ecx[4] );
}
sambowry
I think the reason you got downvoted is that wmemset takes a wide character argument (aka wchar_t), which is 16 bits, not 32. But that's interesting: I never knew that function existed. Neat.
Tadmas
I tested my code, wchar_t is 4 bytes long on my host.
sambowry
what's the output?0D0D0D0D? F00DF00D?
Pod
Ignore my previous comment, I thought that wmemset wasn't working for you, but it is :)
Pod
@sambowry: I guess it depends on the implementation. It's based on an underlying integral type, so your compiler may have chosen int instead of short. After googling a bit, it looks like wchar_t is typically 2 bytes on Windows and 4 bytes on Linux/Mac. Since the asker is using gcc, it's probably Linux, so this would work for him. Still, it's not really portable. Nice solution. +1
Tadmas