Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to memset() memory to a certain pattern instead of a single byte?

I need to write a repeating pattern to memory (e.g. 0x11223344), so that the whole memory looks like (in hex):

1122334411223344112233441122334411223344112233441122334411223344...

I can't figure out how to do it with memset() because it takes only a single byte, not 4 bytes.

Any ideas?

like image 633
bodacydo Avatar asked Jul 27 '10 15:07

bodacydo


People also ask

Does memset write to memory?

memset() will blindly write to the specified address for the number of specified bytes, regardless of what it might be overwriting. It is up to the programmer to ensure that only valid memory is written to.

Why does memset only work with 0 and 1?

CPP. Note: We can use memset() to set all values as 0 or -1 for integral data types also. It will not work if we use it to set as other values. The reason is simple, memset works byte by byte.

What is the difference between memset and memcpy?

memcpy() copies from one place to another. memset() just sets all pieces of memory to the same. For example here sets string length of the string str to * (or whatever second argument of the memset). Here copies the string length of the string src to dest.

What is the use of memset function in c?

The memset() function sets the first count bytes of dest to the value c. The value of c is converted to an unsigned character.


3 Answers

On OS X, one uses memset_pattern4( ) for this; I would expect other platforms to have similar APIs.

I don't know of a simple portable solution, other than just filling in the buffer with a loop (which is pretty darn simple).

like image 106
Stephen Canon Avatar answered Sep 24 '22 18:09

Stephen Canon


An efficient way would be to cast the pointer to a pointer of the needed size in bytes (e.g. uint32_t for 4 bytes) and fill with integers. It's a little ugly though.

char buf[256] = { 0, }; uint32_t * p = (uint32_t *) buf, i;  for (i = 0; i < sizeof(buf) / sizeof(* p); i++) {     p[i] = 0x11223344; } 

Not tested!

like image 23
jkramer Avatar answered Sep 24 '22 18:09

jkramer


Recursively copy the memory, using the area which you already filled as a template per iteration O(log(N)):

int fillLen = ...;
int blockSize = 4; // Size of your pattern

memmove(dest, srcPattern, blockSize);
char * start = dest;
char * current = dest + blockSize;
char * end = start + fillLen;
while(current + blockSize < end) {
    memmove(current, start, blockSize);
    current += blockSize;
    blockSize *= 2;
}
// fill the rest
memmove(current, start, (int)end-current);

What I mean with O(log(N)) is that the runtime will be much faster than if you fill the memory manually since memmove() usually uses special, hand-optimized assembler loops that are blazing fast.

like image 43
Aaron Digulla Avatar answered Sep 24 '22 18:09

Aaron Digulla