内存地址c中的正值或负值?

时间:2009-11-06 18:29:49

标签: c memory-address

在c中,我试图打印出变量的地址和某些功能的地址。 我得到一个是负值,另一个是正值。 我的问题是:为什么C不代表所有的负面价值或所有正值?

这是我的代码:

int foo() { 
     return 0;
}

int main() {

    int a;
    printf("%d\n",&a);

    printf("%d\n",foo);

    return 0;
}

结果如下:

-1075908992 134513684

10 个答案:

答案 0 :(得分:29)

不应以这种方式将内存地址解释为有符号整数。数字的符号取决于最高位集(假设当前正在使用的绝大多数系统使用的是二进制补码表示),因此32位系统上的0x80000000以上的存储器地址将为负数,并且存储器地址低于0x80000000将为正数。这没有什么实际意义。

您应该使用%p修饰符打印内存地址;或者,有些人使用%08x打印内存地址(或64位系统上的%016llx)。这将始终打印为十六进制的无符号整数,这比带符号的十进制整数更有用。

int a;
printf("%p\n", &a);

答案 1 :(得分:7)

要成为最符合标准的,请将格式字符串中的“%p”传递给printf()并将参数强制转换为void*

printf("%p\n", (void*)&a);
printf("%p\n", (void*)foo);

引用标准草案(n1401.pdf)

    7.20.6.1 The fprintf function

8   The conversion specifiers and their meanings are:

p       The argument shall be a pointer to void. The value of the pointer
        is converted to a sequence of printing characters, in an
        implementation-defined manner.

答案 2 :(得分:6)

你应该传递指针格式化程序:

printf("%p\n",foo);

答案 3 :(得分:4)

您以十进制打印出来。您可能希望以十六进制打印出内存位置(使用“%p”)(大多数内存地址按照惯例以十六进制显示)。

答案 4 :(得分:3)

两者都没有符号,但是当转换为有符号整数时,它可能是正数或负数。

顺便说一下,将指针传递给printf并使用设计用于打印整数的格式变量会导致未定义的行为。您应该始终显式转换为正确的类型以获取未指定的或实现定义的行为(取决于强制转换)。

答案 5 :(得分:3)

指针不是有符号整数,更像是无符号整数。但是,您将它们打印出来就好像它们是有符号整数一样。在32位系统上,有几件事可能是32位长:intunsigned intfloat和指针。你不能一般地通过观察它们来判断这些是什么,但它们都意味着不同的东西。 (作为一个实验,你可以传递各种整数并像浮点数一样打印它们,反之亦然:这是一般的不好的做法,但它可以告诉你不同的数据类型确实意味着不同的东西。)

采用可变数量参数的函数(“可变参数”函数)以复杂的方式执行此操作。特别是,它们不检查参数类型。您可以将您喜欢的任何参数传递给printf()和类似的函数,但让它们同意格式说明符是您的问题。这意味着该函数无法使类型正确(就像您将float传递给int foo(int)之类的函数一样。

传递错误类型的参数会导致未定义的行为,如果传递的参数大小错误,则特别容易导致问题。在大多数64位系统上,指针为64位,int为32。

因此,您需要在格式字符串中使用正确的东西。 printf("%p", &a);将打印出a的地址作为指针,这就是您想要的。该标准需要printf("%p", (void *)&a);之类的内容,但实际上这在您可能遇到的任何计算机上都是不必要的。

答案 6 :(得分:1)

您也可以使用printf("%p", &a)%p是指针格式说明符,用于以实现定义的方式输出指针的值。实际上,它与%x几乎相同,但会处理指针大于int的情况。

答案 7 :(得分:0)

printf不是一些神奇的解释工具。如果你给它“%d”它正在显示该变量中的位模式看起来像一个整数。

至于为什么有些指针是负数且有些正数,所有这些意味着有些指针设置了高位,有些指针则没有。给对象的地址实际上只是操作系统的业务(通常有一些硬件帮助)。编程语言没有真正的发言权。

如果我是你,我就不会以这种方式打印地址。如果您确实需要查看它们,请使用“%x”而不是“%d”。这将以十六进制打印它们,这使得更容易确定哪些位是打开的,哪些不是。通常情况下,您要关注的是地址是否为0,如果它们与其他地址的值相匹配。

答案 8 :(得分:0)

除了使用%p之外,您还可以转换为uintptr_t以确保获得未分配的整数。

使用PRIuPTR(或PRIXPTR表示十六进制)格式<inttypes.h>来获取正确的格式说明符:

printf("%" PRIuPTR "\n", (uintptr_t)(void *)&foo);

答案 9 :(得分:-1)

使用以下代码:

printf("%u",&a);