C 如何在没有printf的情况下打印指针地址

C 如何在没有printf的情况下打印指针地址,c,arrays,pointers,printf,C,Arrays,Pointers,Printf,我正在做一个练习,需要打印指针的内存(地址)。使用printf(“%p”,…)很容易做到,但我不允许使用它 你知道我如何不用printf()就可以得到地址吗? 我唯一可以使用的功能是“写入” 以下是我的练习说明: 编写一个函数,该函数接受(const void*addr,size\u t size),并显示 如示例中所示的内存。 您的函数必须声明如下: 你可以这样做。。。您说过禁止使用printf(),但您没有提到sprintf print_bytes(char *ptr, int coun

我正在做一个练习,需要打印指针的内存(地址)。使用
printf(“%p”,…)
很容易做到,但我不允许使用它

你知道我如何不用
printf()
就可以得到地址吗? 我唯一可以使用的功能是“写入”

以下是我的练习说明:

编写一个函数,该函数接受
(const void*addr,size\u t size)
,并显示 如示例中所示的内存。 您的函数必须声明如下:



你可以这样做。。。您说过禁止使用
printf()
,但您没有提到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);
 }

编辑:在OP澄清他们实际上想要转储内存内容之前,我提供了这个答案(澄清之前,他们要求代码表现得像
printf(“%p”,mem\u ptr)

此代码应拼出每个数字(十六进制):

#包括
/*您必须在某个地方提供此功能*/
外部无效写入字符(字符);
字符十六进制数字(整数v){
如果(v>=0&&v<10)
返回“0”+v;
其他的
返回“a”+v-10;/>i)和0xf);
}
}
这里,
print\u address\u hex
是一次打印一个数字的基本算法()。[为了简化我不关心前导零的事情]

该算法的核心是运算符
>
(类似于二进制整数除法)和
&
(类似于二进制余数)。[请注意,这些运算符通常只对基数2、4、8、16、2^n起作用]

我使用了
uintptru\t
使其可移植。此类型(在
中声明)指的是能够容纳指针的集成类型(与体系结构无关)。我们需要一个整数类型,以便可以使用算术运算符(除了指针算术的唯一有效运算符
+
-

您可以像这样尝试:

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

您不必打印内存,您必须将addr中的每个字节转换为十六进制并打印出来,第二部分是用点和星号将每个字节的值转换为字符,如果它不可打印,它将打印点

#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++;
        }
    }
}
#包括
#包括
void ft_putchar(字符c)
{
写(1,&c,1);
}
无效打印\u ascii(常量字符*地址,整数i)
{
int j;
内伦;
j=0;
如果((i+1)%16==0)
len=16;
其他的
len=(i+1)%16;
而(j<16-len)
{
ft_putchar(“”);
ft_putchar(“”);
如果(j%2)
ft_putchar(“”);
j++;
}
如果((16-len)%2)
ft_putchar(“”);
j=0;
而(j=32&&*(地址+i/16*16+j)=10)
ft_putchar('a'+值%16%10);
其他的
ft_putchar('0'+值%16);
}
}
无效打印内存(常量无效*地址,大小)
{
char*ptr;
尺寸i;
如果(地址和大小>0)
{
ptr=(char*)addr;
i=0;
而(i

这段代码适用于您的考试。

“我需要打印指针的内存”嗯,这对我来说有点不清楚。你想打印指针的值还是它指向的内存?@machine\u 1:实现
printf
的代码正是这样做的,所以这当然是可能的。@machine\u 1我在发布的答案中使用
sprintf()
,但输出格式化文本时没有
printf()
是一项简单的任务。想想在
printf()
存在之前,我们是如何输出格式化输出的。或者考虑一下,如果在设计操作系统时实现C库,您将如何实现
printf()
。这很琐碎,只是不方便。我仍然不知道你想做什么
printf(“%p”,…)
打印地址(指针值)。但在您的评论中,“0000 0000 1700 0000 9600 0000 ff00 0000”看起来更像该地址的16字节内存的内容;这是128位,可能比指针值大。@GautierLemaire:你想做什么还不清楚。什么是“数组中的地址”?你的意思是你有一个指针数组,你想打印数组中每个元素的值吗?问你的问题最清晰的方式可能是使用
printf(“%p”,…)
显示做你想做的事情的代码,并询问如何在不使用
printf
的情况下做同样的事情。(由于这似乎是一个家庭作业问题,我很犹豫是否提供完整的答案,尽管我愿意将代码发送给您的讲师,并附上您的姓名。)OP明确表示他不能使用
printf()
感谢您的回答,这是一个很好的方法。但是,您是否可以仅使用“写入”功能来执行此操作?@GautierLemaire:Why
write
?这是POSIX特有的。如果您想要可移植性,您应该使用类似于
fputc
fputs
@DanielH:正如问题所述,我没有注意到。对不起,吵闹了。(我的问题仍然适用于创建任务的人,但不适用于OP。)@GautierLemaire:什么地址?如果您试图执行与printf(“%p”,…)
等效的操作,请在问题中说明。这是你所写内容的含意,但与你的一些评论相矛盾。“指针地址”可能意味着指针对象的存储地址,但我认为您需要指针的值。
 write(1, string, strlen(string)); /* 1 = STDOUT */
#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));
    }
}
#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;
}
0000 0000 1700 0000 9600 0000 ff00 0000 
0c00 0000 1000 0000 1500 0000 2a00 0000 
0000 0000 0000 0000 
#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++;
        }
    }
}