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
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
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.
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).
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 */