7

I'm learning how numbers are represented in memory. I want to know how to print the actual representation (binary or hexadecimal) in memory of some int and float variables.

I'd like to see what happens with that numbers when adding or subtracting it causes overflow, for example.

How can I access memory and print it?

John Slegers
  • 45,213
  • 22
  • 199
  • 169
aledruetta
  • 107
  • 1
  • 2
  • 8

6 Answers6

11

You would need to assign a pointer to the variable in question to a char *, and treat it as an array of bytes of length sizeof(variable). Then you can print each byte in hex using the %X format specifier to printf.

You can define a function like this:

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");
}

And call it like this:

int x = 123456;
double y = 3.14;
print_bytes(&x, sizeof(x));
print_bytes(&y, sizeof(y));
dbush
  • 205,898
  • 23
  • 218
  • 273
  • Should probably make that `unsigned char` and use `%hhX` as the format specifier. – John Bode Feb 12 '16 at 15:04
  • @JohnBode Good call. Edited. – dbush Feb 12 '16 at 15:18
  • @dbush, your example prints 40 E2 01 00 (int 123456 -> 32-bits). I think it should be 00 01 E2 40. This is because how memory stores numbers? Or should I modify the loop? – aledruetta Feb 12 '16 at 15:48
  • 1
    @AleD This is because of the [endianness](https://en.wikipedia.org/wiki/Endianness) of your machine, which is the byte ordering of integer typs. Most machines these days (as is the case in this example) are little-endian, which means the least significant byte is first. If you ran this on a Sun machine, which is big-endian, you'd see the most significant byte first. – dbush Feb 12 '16 at 15:51
4

... to print the actual representation (binary ...

To convert any variable/object to a string that encodes the binary form uses a helper function that converts memory into a "binary" string. This method also handles function pointers. Uses C99 or later.

#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;
}

Output (Note: depending in endian-ness, results may vary)

Sample
double pi:0100000000001001001000011111101101010100010001000010110100011000  
int 42:00000000000000000000000000101010

This approach is easy to adapt to hexadecimal form.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
2

Call 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) ;
    }
}

It has been tested successfully, working with any variable of less than or equal to 64 bits. This will probably work correctly with variables with other sizes (Not Tested).

Calling:

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

Output:

1100010111110000000000000000000011100000000000000000000100010111
Shamsul Arefin
  • 661
  • 7
  • 15
1

Let's say you have a int variable called memory. Make sure you see how many bits it is; for many processors an int is 32 bits as well as a memory address. So you need to loop through each bit, like this:

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

This simple method ORs each bit with 1 and shifts each bit by 1.

Matt Leverich
  • 39
  • 2
  • 8
  • better using while loop with memory with quotient, reminder for avoid processor bit problem. – Yoon-Geun Kwon Feb 12 '16 at 14:35
  • @Yoon-GeunKwon: Shifting is not dependent on byte- or bit-order. It's defined mathematically (division/multipication by 2 to the n) according to the C11 draft standard `6.5.7 Bitwise shift operators`. – EOF Feb 12 '16 at 14:45
  • This assumes 32-bit int, which may not be true – Mr. E Feb 12 '16 at 14:49
1
#include <stdio.h>
#include <stdlib.h>

void print_bits ( void* buf, size_t size_in_bytes )
{
    char* ptr = (char*)buf;

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

int main ( void )
{
    size_t n;
    scanf("%d", &n);
    print_bits(&n, sizeof(n));
    return 0;
}

This prints bits of the specified object (n here) with the specified size (in bytes).

Anton_a235
  • 11
  • 3
1

@dbush, @Anton, I mixed your codes. It's okay?

#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");
}
aledruetta
  • 107
  • 1
  • 2
  • 8