How to print a pointer address without printf

后端 未结 4 2083
面向向阳花
面向向阳花 2021-01-07 00:30

I\'m doing an exercise in which I need to print the memory (address) of a pointer. It would be easy to do it with printf(\"%p\", ..) but I\'m not allowed to use

相关标签:
4条回答
  • 2021-01-07 00:57

    You can try like:

    #include <stdio.h>
    
    void print_memory(const void *addr, size_t size)
    {
        size_t printed = 0;
        size_t i;
        const unsigned char* pc = addr;
        for (i=0; i<size; ++i)
        {
            int  g;
            g = (*(pc+i) >> 4) & 0xf;
            g += g >= 10 ? 'a'-10 : '0';
            putchar(g);
            printed++;
    
            g = *(pc+i) & 0xf;
            g += g >= 10 ? 'a'-10 : '0';
            putchar(g);
            printed++;
            if (printed % 32 == 0) putchar('\n');
            else if (printed % 4 == 0) putchar(' ');
        }
    }
    
    int main(void) {
    int tab[10] = {0, 23, 150, 255, 12, 16, 21, 42};
    
    print_memory(tab, sizeof(tab)); return (0);
    
        return 0;
    }
    

    Output

    0000 0000 1700 0000 9600 0000 ff00 0000 
    0c00 0000 1000 0000 1500 0000 2a00 0000 
    0000 0000 0000 0000 
    
    0 讨论(0)
  • 2021-01-07 01:05

    You don't have to print the memory, you have to transform each byte from addr in hexadecimal and print it, the second part with dots and asterisk is transform the value of each byte in char, if it isn't printable it will print dot.

    #include <string.h>
    
    #include <unistd.h>
    
    void    ft_putchar(char c)
    {
        write(1, &c, 1);
    }
    
    void    print_ascii(const char *addr, int i)
    {
        int j;
        int len;
    
        j = 0;
        if ((i + 1) % 16 == 0)
            len = 16;
        else
            len = (i + 1) % 16;
        while (j < 16 - len)
        {
            ft_putchar(' ');
            ft_putchar(' ');
            if (j % 2)
                ft_putchar(' ');
            j++;
        }
        if ((16 - len) % 2)
            ft_putchar(' ');
        j = 0;
        while (j < len)
        {
            if (*(addr + i / 16 * 16 + j) >= 32 && *(addr + i / 16 * 16 + j) <= 126)
                ft_putchar(*(addr + i / 16 * 16 + j));
            else
                ft_putchar('.');
            j++;
        }
        ft_putchar('\n');
    }
    
    void    print_hex(unsigned char value, int index)
    {
        if (index < 2)
        {
            print_hex(value / 16, index + 1);
            if (value % 16 >= 10)
                ft_putchar('a' + value % 16 % 10);
            else
                ft_putchar('0' + value % 16);
        }
    }
    
    void    print_memory(const void *addr, size_t size)
    {
        char    *ptr;
        size_t  i;
    
        if (addr && size > 0)
        {
            ptr = (char*)addr;
            i = 0;
            while (i < size)
            {
                print_hex(*(ptr + i), 0);
                if (i % 2)
                    ft_putchar(' ');
                if ((i + 1) % 16 == 0 || (i + 1) == size)
                    print_ascii(addr, i);
                i++;
            }
        }
    }
    

    This code works for your exam.

    0 讨论(0)
  • 2021-01-07 01:06

    EDIT: I provided this answer before the OP clarified they actually wanted to dump memory contents (before clarifying it they asked for code to act like printf("%p", mem_ptr).

    This code should spell out each digit (in hex):

    #include <stdint.h>
    
    /* you must provide this function somewhere */
    extern void write_char(char);
    
    char hex_digit(int v) {
        if (v >= 0 && v < 10)
            return '0' + v;
        else
            return 'a' + v - 10; // <-- Here
    }
    
    void print_address_hex(void* p0) {
        int i;
        uintptr_t p = (uintptr_t)p0;
    
        write_char('0'); write_char('x');
        for(i = (sizeof(p) << 3) - 4; i>=0; i -= 4) {
            write_char(hex_digit((p >> i) & 0xf));
        }
    }
    

    Here, print_address_hex is a basic algorithm for printing digits one at a time (like this one). [to simplify things I didn't care about leading zeros]

    The core of the algorithm are the operators >> (acts like binary integer division) and & (acts like binary remainder). [notice that those operators will only work for bases 2, 4, 8, 16, 2^n in general].

    I used uintptr_t to make it portable. This type - declared in <stdint.h> - refers to an integral type capable of holding a pointer (architecture independent). We need an integral type so that we can use arithmetic operators (besides + and -, the only valid operators for pointer arithmetic).

    0 讨论(0)
  • 2021-01-07 01:12

    You could do something like this... You said printf() is off limits, but you said nothing about sprintf.

     print_bytes(char *ptr, int count)
     {
       int i;
       char string[1024];
       string[0] = 0;
       for(i = 0; i < count; i++)
       {
         sprintf(string,"%s %2x", string, *(ptr+i));
       }
       puts(string);
     }
    

    This should loop through count bytes printing out each hexadecimal byte starting from the passed in address in ptr.

    Obviously, this makes no attempt to properly size the string array. That should be dynamically sized based on the passed in count.

    To substitute write() for puts(), you could use:

     write(1, string, strlen(string)); /* 1 = STDOUT */
    
    0 讨论(0)
提交回复
热议问题