como imprimir bits de memoria en c

5 minutos de lectura

avatar de usuario
aledruetta

Estoy aprendiendo cómo se representan los números en la memoria. Quiero saber cómo imprimir la representación real (binaria o hexadecimal) en la memoria de algunas variables int y float.

Me gustaría ver qué sucede con esos números cuando sumarlos o restarlos provoca un desbordamiento, por ejemplo.

¿Cómo puedo acceder a la memoria e imprimirla?

  • utilizar printf() con especificador de acceso %u

    –Jaffer Wilson

    12 de febrero de 2016 a las 14:34

  • Si una de las respuestas abordó su pregunta, considere aceptarla.

    – dbush

    24 de febrero a las 17:26

avatar de usuario
arbusto

Debería asignar un puntero a la variable en cuestión a un char *y trátelo como una matriz de bytes de longitud sizeof(variable). Luego puede imprimir cada byte en hexadecimal usando el %X especificador de formato para printf.

Puedes definir una función como esta:

void print_bytes(void *ptr, int size) 
{
    unsigned char *p = ptr;
    int i;
    for (i=0; i<size; i++) {
        printf("%02hhX ", p[i]);
    }
    printf("\n");
}

Y llámalo así:

int x = 123456;
double y = 3.14;
print_bytes(&x, sizeof(x));
print_bytes(&y, sizeof(y));

  • Probablemente debería hacer eso unsigned char y use %hhX como especificador de formato.

    – Juan Bode

    12 de febrero de 2016 a las 15:04

  • @JohnBode Buena decisión. Editado.

    – dbush

    12 de febrero de 2016 a las 15:18

  • @dbush, su ejemplo imprime 40 E2 01 00 (int 123456 -> 32 bits). Creo que debería ser 00 01 E2 40. Esto se debe a que, ¿cómo almacena la memoria los números? ¿O debería modificar el bucle?

    – aledruetta

    12 de febrero de 2016 a las 15:48

  • @AleD Esto se debe a la endianidad de su máquina, que es el ordenamiento de bytes de tipos enteros. La mayoría de las máquinas en estos días (como es el caso en este ejemplo) son little-endian, lo que significa que el byte menos significativo es el primero. Si ejecutó esto en una máquina Sun, que es big-endian, vería primero el byte más significativo.

    – dbush

    12 de febrero de 2016 a las 15:51

avatar de usuario
chux – Reincorporar a Monica

… para imprimir la representación real (binario …

Para convertir ninguna variable/objeto a una cadena que codifica la forma binaria utiliza una función auxiliar que convierte la memoria en una cadena “binaria”. Este método también maneja punteros de función. Utiliza C99 o posterior.

#include <stdio.h>
#include <assert.h>
#include <limits.h>

//                                    .... compound literal .......
#define VAR_TO_STR_BIN(x) obj_to_bin((char [sizeof(x)*CHAR_BIT + 1]){""}, &(x), sizeof (x))

char *obj_to_bin(char *dest, void *object, size_t osize) {
  const unsigned char *p = (const unsigned char *) object;
  p += osize;
  char *s = dest;
  while (osize-- > 0) {
    p--;
    unsigned i = CHAR_BIT;
    while (i-- > 0) {
      *s++ = ((*p >> i) & 1) + '0';
    }
  }
  *s="\0";
  return dest;
}

int main(void) {
  int i = 42;
  double d = 3.1415926535897932384626433832795;
  printf("Sample\ndouble pi:%s\nint 42:%s\n", VAR_TO_STR_BIN(d), VAR_TO_STR_BIN(i) );
  return 0;
}

Salida (Nota: dependiendo del endian-ness, los resultados pueden variar)

Sample
double pi:0100000000001001001000011111101101010100010001000010110100011000  
int 42:00000000000000000000000000101010

Este enfoque es fácil de adaptar a la forma hexadecimal.

  • ¡Hola! ¿Puedes explicar el “(char [sizeof(x)*CHAR_BIT + 1]){“”}”? No entiendo por qué hay un “+ 1” y un “{“”}” :/

    – Hedwin Bonnavaud

    8 sep 2021 a las 11:36

  • @HedwinBonnavaud ¿Qué tan familiarizado está con literales compuestos? ¿Cuál es el tamaño de memoria necesario para almacenar el cuerda “00001111”? 8 o 9?

    – chux – Reincorporar a Monica

    8 sep 2021 a las 11:39


  • lo tengo, agregas +1 para mantener el espacio para almacenar ‘\ 0’ al final, ¿verdad?

    – Hedwin Bonnavaud

    8 sep 2021 a las 13:10


  • @HedwinBonnavaud Sí +1 para el carácter nulo.

    – chux – Reincorporar a Monica

    8 sep 2021 a las 13:39

  • ok gracias por este agradable y útil código por cierto

    – Hedwin Bonnavaud

    8 sep 2021 a las 13:50


Digamos que tiene una variable int llamada memoria. Asegúrese de ver cuántos bits tiene; para muchos procesadores, un int es de 32 bits, así como una dirección de memoria. Así que necesitas recorrer cada bit, así:

unsigned int memory = 1234;
for (int i = 0; i < 32; i++)
{
  printf("%d ", memory >> i & 1);
}

Este método simple combina cada bit con 1 y cambia cada bit por 1.

  • mejor usando el ciclo while con memoria con cociente, recordatorio para evitar problemas con los bits del procesador.

    – Yoon-Geun Kwon

    12/02/2016 a las 14:35


  • @Yoon-GeunKwon: el cambio no depende del orden de bytes o bits. Se define matemáticamente (división/multiplicación por 2 a la n) según el proyecto de norma C11 6.5.7 Bitwise shift operators.

    – FEO

    12 de febrero de 2016 a las 14:45


  • Esto supone un int de 32 bits, lo que puede no ser cierto

    – Sr. E

    12 de febrero de 2016 a las 14:49

@dbush, @Anton, mezclé sus códigos. ¿Está bien?

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

void print_bytes( void *ptr, size_t size ) ;

int main( void )
{
    int x = 123456 ;
    double y = 3.14 ;

    print_bytes( &x, sizeof(x) ) ;
    print_bytes( &y, sizeof(y) ) ;

    return 0 ;
}

void print_bytes( void *ptr, size_t size )
{
    //char *buf = (char*) ptr;
    unsigned char *p = ptr ;

    for( size_t i = 0; i < size; i++ )
    {
        printf( "%02hhX ", p[i] ) ;
    }
    printf( "\n" ) ;

    for( size_t i = 0; i < size; i++ )
    {
        for( short j = 7; j >= 0; j-- )
        {
            printf( "%d", ( p[i] >> j ) & 1 ) ;
        }
        printf(" ");
    }
    printf("\n");
}

Llamada print_bits(memory address of variable, size of variable in byte).

void print_bits(void *ptr, int size) //ptr = memory address of variable, size = size of variable in byte
{
    long long *ch = ptr;
    int size_bits = size * 8;
    for(int i = size_bits-1; i>=0; i--){
        printf("%lld", *ch >> i & 1) ;
    }
}

Ha sido probado con éxito, trabajando con cualquier variable menor o igual a 64 bits. Esto probablemente funcionará correctamente con variables de otros tamaños (no probado).

Vocación:

double d = -7.92282286274e+28;
print_bits(&d, sizeof(d));

Producción:

1100010111110000000000000000000011100000000000000000000100010111

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad