Preforming manipulations on C memory addresses as char* to output.

Viewed 89

I'm attempting to print the address of all arguments in argv as segmented chars.

The address of argv[0]

0x7ffdf0451078

I want to print this as

0x7ffd f0 45 10 78

Then truncate the beginning id, and print this into a formatted gird similar to

 +------+------+------+------+
 |  f0  |  45  |  10  |  78  | 
 +------+------+------+------+

I'm assuming the easiest way to accomplish this is to hold the address of argv[0] as a string, or char array, and then do some manipulation to that string / array.

However I have not been able to get the address into any type of container thus far.

3 Answers

You could do

char str[100];
sprintf(str, "%p", argv[0]);

Now str would have "0x7ffdf0451078" if argv[0] is 0x7ffdf0451078.

You need only the f0451078 part. ie, the str+6 part.

Now use sscanf() like

char d[4][3];
sscanf(str+6, "%2s%2s%2s%2s", d[0], d[1], d[2], d[3]);

and print them as you need.

If you used the %x format specifier instead of %p, use str+4.

Demo here.

void *ptr = argv[0];
printf("%02x %02x %02x %02x\n",
       (int)((ptr / 0x1000000) & 0xff),
       (int)((ptr / 0x10000) & 0xff),
       (int)((ptr / 0x100) & 0xff),
       (int)(ptr & 0xff));

If you want control over the representation of the pointer, you may wish to convert it to intptr_t so you have confidence in the behavior of printf style specifiers. (The output format of %p is implementation-defined.)

#include <stdio.h>
#include <inttypes.h>

int main(int argc, char *argv[])
{
    intptr_t address = (intptr_t) &argv[0];

    char repr[1 + 2*sizeof(intptr_t)]; // 2 chars per byte plus a '\0'
    snprintf(repr, sizeof repr, "%" PRIxPTR, address); // this is the magic

    printf("0x%.4s %.2s %.2s %.2s %.2s\n", repr, repr+4, repr+6, repr+8, repr+10);
    // output: 0x7ffd f0 45 10 78

    printf("+------+------+------+------+\n");
    printf("|  %.2s  |  %.2s  |  %.2s  |  %.2s  |\n", repr+4, repr+6, repr+8, repr+10);
    printf("+------+------+------+------+\n");
    // output:
    // +------+------+------+------+
    // |  f0  |  45  |  10  |  78  | 
    // +------+------+------+------+
}

I found this question for formatting an intptr_t, and I used the precision field of the %s format specifier to print sections of the string that snprintf created.

Although repr's size is defined in terms of sizeof(intptr_t), the printing code here assumes a 24 bit address.

Related