实现printf时%p的结果不正确

时间:2014-12-16 13:02:34

标签: c printf

我正在处理我自己的printf代码,我遇到了2个问题,希望您能帮助我。

第一个是%p选项:

此选项为我提供了十六进制形式的void*的指针地址。 所以我正在做的是:

void    printp(void *thing)
{
    dectohex((long)&thing, 1);
}  

其中dectohex只是将decimal转换为hex的函数。 除最后3个字符外,结果始终是正确的。总是。例如:

me : 0x5903d8b8 , printf : 0x5903da28.

这些角色经常不会改变,而另一部分在每次通话时都会发生变化,就像它应该的那样。

我遇到的另一个问题是%O选项。我无法将签名的int转换为unsigned intprintfnegative int's打印了大量数字,并且没有任何演员似乎有效,因为无论如何我都无法存储它。

编辑: 非常感谢你的答案,所以显然对于第一个问题我只是有点愚蠢。对于第二个问题,我将尝试您给我的不同解决方案,如果我设法做到这一点,请更新您。

再次非常感谢您的时间和耐心,并对我的回复延迟感到抱歉,我检查了电子邮件提醒以获得任何答案,但它显然不起作用。

REEDIT:在仔细阅读了我的第二个问题的答案之后,我想你们有些人认为我问过%o或%0。我真的在谈论%O,就像我认为的那样。在那个人告诉我"%O:long int参数被转换为无符号八进制"。我的问题是在将long int转换为八进制之前,我需要将它转换为无符号的东西。

4 个答案:

答案 0 :(得分:3)

如果定义了uintptr_t/intmax_t(它是可选的),将指针转换为该整数类型然后打印。

否则,如果sizeof(uintmax_t) >= sizeof (void *),请转换为uintmax_tuintmax_t是必需的类型,但可能不够大。

void printp(void *thing) {
  uintptr_t j = (uintptr_t) thing;
  char lst[(sizeof j * CHAR_BIT + 3)/ 4 + 1]; // Size needed to print in base 16
  char *p = &lst[sizeof lst] - 1;
  *p = '\0';
  do {
    p--;
    *p = "0123456789ABCDEF"[j%16];
    j /= 16;
  } while (p > lst);
  fputs(p, stdout);
}

%O问题可能是签名延期问题。 (@mafso)确保使用的贵重物品是未签名的,例如unsignedunsigned long。没有看到代码很难确定。

答案 1 :(得分:2)

关于你要做的第一个问题,只是为了确保你想打印东西的地址(注意事物本身就是一个指针)或事物origin的地址(指向指针的指针)?

您当前正在打印指针指针。

更改

dectohex((long)&thing, 1); 

dectohex((long)thing, 1); 

如果是这样的话。

关于%O问题,您能举一个代码示例吗?

答案 2 :(得分:1)

你的演员阵容需要“unsigned long long”。

指针是未签名的,但签名很长。

任何数据类型中的位数都取决于实现;但是现在长期和无符号长整数通常是32位。

编辑:为了更清楚,你不能指望C,C ++或Objective-C中的位数,它总是依赖于实现。例如,有一次共有九位字节和三十六位字。这就是为什么互联网协议总是指定“八位字节” - 八个一组的组 - 而不是“字节”。

这是Java的一个优点,因为每种数据类型中的位数都是严格确定的。

答案 3 :(得分:0)

关于零填充和负整数的第二个问题,这似乎与关于十六进制输出的第一个问题完全分开。你可以处理这样的负数(虽然在32位中它不能用值-2147483648,即0x80000000)。

#include <stdio.h>
#define MAXDIGITS   21

int printint(int value, int zeropad, int width)
{
    int i, z, len = 0;
    char strg [MAXDIGITS+1];
    strg [MAXDIGITS] = 0;

    if (value < 0) {
        value = - value;
        putchar ('-');
        len = 1;
    }

    for (i=MAXDIGITS-1; i>=0; i--) {
        strg [i] = '0' + value % 10;
        if ((value /= 10) == 0)
            break;
    }

    if (zeropad)
        for (z=MAXDIGITS-i; z<width; z++) {
            putchar ('0');
            len++;
        }

    for (; i<MAXDIGITS; i++) {
        putchar (strg [i]);
        len++;
    }
    return len;
}

int main (int argc, char *argv[])
{
    int num = 0, len;
    if (argc > 1) {
        sscanf (argv[1], "%d", &num);
        // try the equivalent of printf("%4d, num);
        len = printint (num, 0, 4);
        printf ("   length %d\n", len);
        // try the equivalent of printf("%04d, num);
        len = printint (num, 1, 4);
        printf ("   length %d\n", len);
    }
    return 0;
}