Programación en C: strtol() y manejo de bytes NUL

Digamos que tengo una dirección y un desplazamiento como:

   char* base_addr = "\x00\x00\x00\xb7";
   char* addr_offset = (user input);

y quiero agregar base_addr y addr_offset juntos. ¿Tendría que escribir mi propia función strtol() que no termina en un NUL o hay otra forma de agregar con éxito las dos direcciones?

EDIT:

Olvidé decir que esto es Linux x86.

preguntado el 12 de junio de 12 a las 21:06

No me queda claro exactamente a qué te refieres con agregar la entrada del usuario a una cadena existente. Pero, básicamente, sí, escribe tu propia función. Esto debería ser trivial. -

1 Respuestas

base_addr es en realidad un valor entero de 32 bits, que simplemente se ha codificado utilizando constantes de bytes. Simplemente debe emitir el tipo del puntero a unsigned long, luego llame strtol() en la cadena ingresada por el usuario, y suma los dos.

Es tonto codificar un puntero usando una cadena de esa manera. Por un lado, C agregará un byte NUL al final de la cadena, por lo que ahora su valor de 32 bits toma 5 bytes, y con los bytes de relleno agregados, podría terminar usando 8 bytes para almacenar su puntero, exactamente el doble de lo que se necesita. . Mejor hacerlo de esta manera:

char base_addr[] = {'\x00', '\x00', '\x00', '\xb7'};

Aún mejor decir lo que quieres decir, siempre que el compilador te permita hacer el tipo de conversión:

unsigned char *base_addr = (unsigned char *)0xb7000000;

Acabo de comprobar y GCC te permite hacer lo anterior sin errores ni advertencias.

EDITAR: Oh, está bien, la verdadera pregunta es cómo obtener acceso a los bytes dentro de un valor entero.

Debería poder hacer esto simplemente jugando con los punteros:

unsigned long base_adr = 0xb700000000;
unsigned char *p = (unsigned char *)&base_adr;

El truco anterior funciona con tipos enteros. La otra forma de hacerlo es con una unión C:

typedef union
{
    char bytes[4];
    unsigned long n;
    unsigned char *ptr;
} ADR_WINDOW;

ADR_WINDOW x;

x.n = 0xb700000000;
assert(x.bytes[3] == 0xb7); // on a little-endian computer
assert(x.bytes[0] == 0xb7); // on a big-endian computer

El truco de la unión funciona para cualquier tipo y es la única forma portátil de hacer trucos de mala calidad, como mirar los bits dentro de un valor flotante.

Respondido el 13 de junio de 12 a las 01:06

¿Cómo puedo volver a convertir el largo sin firmar en una cadena después de haber sumado los dos (lo necesito como una cadena que contiene bytes little endian)? - Bhubhu Hbuhdbús

No creo que eso sea correcto. Puedes lanzar cualquier cosa a char*. ¿Por qué debería ser diferente para enteros y flotantes? Usar uniones como esa es un comportamiento técnicamente indefinido. deberías preferir uintptr_t/uint32_t en lugar de unsigned long. - Piotr Praszmo

Buen punto sobre uintptr_t. Pero en mi experiencia, tratar de acceder a los bits dentro de un flotador es una forma rápida de hacer que GCC se queje de los "punteros con juegos de palabras". No estoy seguro de que tenga razón acerca de que el truco de la unión es un comportamiento indefinido; eso es lo más parecido que tiene C a una forma oficial de hacer esto, y he descubierto que es completamente portátil, incluso para chips DSP. Por supuesto, el orden de los bytes dentro de un valor entero depende de la endianidad del sistema. - steveha

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.