2010-07-27 6 views
11

Estoy frente hoy con un problema en el que tengo que cambiar la memoria a un determinado patrón como 0x 11223344, de modo que toda la memoria se parece (en hexadecimal):¿Cómo memset() la memoria a un cierto patrón en lugar de un solo byte?

1122334411223344112233441122334411223344112233441122334411223344... 

no puedo encontrar la manera de hazlo con memset() porque solo toma un solo byte, no 4 bytes.

¿Alguna idea?

Gracias, Boda Cydo.

Respuesta

3

Una manera eficiente sería convertir el puntero a un puntero del tamaño necesario en bytes (p. uint32_t para 4 bytes) y llenar con enteros. Aunque es un poco feo.

char buf[256] = { 0, }; 
uint32_t * p = (uint32_t *) buf, i; 

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

No se ha probado!

+6

Lo único a tener en cuenta es que' buf' podría no satisfacer los requisitos de alineación para un 'uint32_t' en su plataforma. Si' buf' es el resultado de un 'malloc', no necesita preocuparse por esto, pero si se pasa (por ejemplo) como un argumento por código que usted no controla, usted Será necesario que verifique la alineación antes de escribir de esta manera, o de lo contrario, se generarán accesos no válidos en algunos plataformas. –

+1

Otra cosa a tener en cuenta puede ser endianness, si se ejecuta en una computadora pequeña endian y el llenado y la lectura se realizan utilizando tipos con diferentes tamaños (es decir, rellenando con int pero leyendo con char) –

+2

Esto no es muy eficiente; usar 'memmove()' como en mi ejemplo es mucho, mucho más rápido porque usa operaciones especiales de ensamblador y código optimizado a mano. –

4

Puede configurar la secuencia en algún lugar y luego copiarla usando memcpy() hasta donde lo necesite.

9

En OS X, se usa memset_pattern4() para esto; Esperaría que otras plataformas tengan API similares.

No sé de una solución portátil simple, que no sea simplemente llenar el búfer con un bucle (que es bastante simple).

+2

Olvidé que podía usar loop. Gracias por recordar. Probándolo con bucle ahora. – bodacydo

+0

@bodacydo: lol. literalmente. nos sucede a todos nosotros :( – aib

3

Bueno, el método normal de hacer que es configurar manualmente los primeros cuatro bytes, y luego memcpy(ptr+4, ptr, len -4)

Esto copia los primeros cuatro bytes en los segundos cuatro bytes, a continuación, copia los segundos cuatro bytes en la tercera, y así.

Tenga en cuenta que esto "normalmente" funciona, pero no está garantizado, dependiendo de la arquitectura de su CPU y su biblioteca de tiempo de ejecución de C.

+6

El comportamiento de 'memcpy' no está definido si los buffers de origen y destino se superponen. Esto probablemente funcionará en algunas plataformas, pero ciertamente no funcionará en muchos otros. –

+1

Esto sobrescribirá los primeros cuatro bytes con lo que sea que esté en los segundos cuatro bytes. Además, 'memcpy' no se debe usar con rangos superpuestos. – bstpierre

+0

Está comentando mi mensaje original o editado. memcpy es (dest, src, len), que tengo ahora correcto.(Lo tuve al principio al revés, pero pensé que lo había reparado antes de tu comentario) –

6

copiar recursivamente la memoria, utilizando el área que ya está lleno como plantilla por iteración (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); 

[EDIT] Lo que quiero decir con "O (log (n))" es que el tiempo de ejecución será mucho más rápido que si se llena la memoria manualmente desde memmove() por lo general utiliza bucles ensamblador especiales, optimizado a mano que están ardiendo rápido.

+7

Son O (log (n)) llamadas a 'memmove'; la complejidad real sigue siendo O (n). –

4

Si su patrón encaja en un wchar_t, puede utilizar wmemset() como lo hubiera usado memset().

0

Usar "memcpy" o "memset" quizás no sea el método eficiente.

No abandona el uso de bucles como "para" o "mientras", cuando la función definida por lib hace lo mismo.

Cuestiones relacionadas