thebaconator
thebaconator

Reputation: 313

Given a memory address, how do I print the byte located at that address in C?

Still a novice to C and the different things I am finding online as to how this is done are confusing me.

I have an address converted to an unsigned long value in order to verify that something is at that address in /proc/self/maps.

Once verified, I want to print the byte that is at that address.

From what I am gathering, the address itself is simply a pointer to that byte, so I need to dereference the memory address to get the byte.

So if I wanted to print that byte as a hex number, it would simply be:

printf("%02x", *address)

Any input would be appreciated. Thanks!

Upvotes: 1

Views: 1576

Answers (2)

0___________
0___________

Reputation: 67546

#define UCPTR(addr)   (volatile unsigned char*)(addr) 

printf("0x%02hhx", *UCPTR(address));

To prevent question why volatile?

#define UCPTR(addr)   (volatile unsigned char*)(addr) 
#define NVUCPTR(addr)   (unsigned char*)(addr) 

void foo()
{
    while(*NVUCPTR(0x4564));
}

void bar()
{
    while(*UCPTR(0x4564));
}

and the resulting code:

foo:
        cmp     BYTE PTR ds:17764, 0
        je      .L1
.L3:
        jmp     .L3
.L1:
        ret
bar:
.L6:
        movzx   eax, BYTE PTR ds:17764
        test    al, al
        jne     .L6
        ret

I think that the code is self explanatory

Can it be archived other way? Yes, but not portable, for example:

void foo()
{
    while(*NVUCPTR(0x4564)) asm("":::"memory");
}

https://godbolt.org/z/5Jkhp5

Upvotes: 1

Petr Skocik
Petr Skocik

Reputation: 60067

printf("%02x", (unsigned)*(unsigned char*)the_address_as_an_integer_or_pointer);

Explanation:

If you want to fetch a value from an address, it needs a pointer type. So you cast to a pointer to a char. (Strict aliasing permits fetching any value through a pointer to a character type, other pointer types are more limited). Casting to signed char * would lead to sign-extension (undesirable if you want to print the value as an unsigned) so you cast to *unsigned char. Then you dereference (*). Such a *(unsigned char*)address has type unsigned char, which gets promoted to int when passed through the ... of printf. That usually works with "%x", but to fully satisfy the standard, "%x" requires an unsigned and thence the final cast to unsigned.

Upvotes: 2

Related Questions