繁体   English   中英

打印指针变量的地址

[英]printing the address of a pointer variable

我了解到,在c中打印变量的地址时,我们使用unsigned int(格式字符串中的%u )。
其范围是从0到65535。现在一个整数占用4个字节的内存,这意味着最多可以存储16384(65536/4)个整数。 如果我们尝试声明一个数组int a[20000]并获取其每个元素的地址,将会发生什么?

#include<stdio.h>
int main(void)
{
    int a[20000];
    for(i=0; i<19999; i++])
        printf("%u", &a[i]);
}

在C的早期,一个指针和一个int类型相似,并且您可以安全地从一个指针转换为另一个指针,然后再次返回。 在那个早期,指针和整数都长16位。 在int现在为32位的32位系统上,这仍然是正确的。 但这在64位系统上是错误的,因为指针的长度为64位,而int仅为32位。

所以我不知道您在哪里以及如何得知在c中打印变量的地址时,我们使用unsigned int(%u) ,但会尽快将其忘记,因为通常情况下这是错误的 打印地址的唯一简单方法是%p因为系统会自动将大小调整为16、32或64位。

并且不再将指针转换为int或相反侧,因为它高度不可移植。 在另一篇 文章中一种更可移植的方式(在C99标准变体上)是#include <stdint.h> ,然后将指针转换为intptr_t (然后返回)。 保证此整数类型为指针的大小。

而且,我几乎忘记了65536 = 0x10000 = 2 16和2 32 =4294967296。因此,您与现实相距不远,而且的确如此,在较旧的16位系统中,您无法使用int array[40000]因为int为16位长,数组将耗尽所有可用内存。

但是在32位系统上,您可以寻址4 Gb的内存,因此int array[20000]是无害的。

指针是一个内存地址,您可以在其中找到一些数据。 我们可以使用sizeof()运算符找到指针变量的size。 因此它的大小不取决于它指向的内容,而是取决于系统上占用的内存地址的多个字节,对于32位编译器为4,对于64位编译器为8。

如果我们声明了一个指针double j,则j的类型为double ,即“指向double的指针”。

%p是用于打印指针的正确格式说明符。 %p以十六进制表示形式输出地址。

有时人们使用%u和%x(十六进制形式的无符号int)说明符来打印指针变量。 但是,为%x或%u参数传递指针是未定义的行为。

但是它可以与32位编译器(如代码块)一起使用,这是因为unsigned int和指针的大小在此处相同。 (两个字节)

(假设int和指针具有相同的宽度是错误的。对于在x64上运行的GCC 64位和MSVC 64位,sizeof(void *)== 8,而sizeof(unsigned int)== 4。碰巧在某些架构上,指针和整数的大小相同,例如PDP-11 / 34a或当今的大多数32位架构,但是编写依赖于它的代码是极其不明智的。

您可以按照以下步骤添加额外的2行并进行验证:

printf(“ unsigned int的大小为%lu \\ n”,sizeof(unsigned int)); printf(“指针大小为%lu \\ n”,sizeof(int *));

在具有64位操作系统的64位GCC计算机上,这应该分别给您4和8)

在GCC 64位计算机上,%x将指针转换为无符号整数(32位长度)。 指针的大小为8字节(64位)。 使用%p进行打印将以其完整大小(64位)打印整个指针。 但是,当您使用%x打印时,仅低32位被打印。 因此,使用%p打印指针始终是安全的。

实际上,在旧的16位编译器(如turbo c)上,无符号整数的范围为0到65536。 如今,所有系统都具有32或64位架构,其无符号整数范围为0到4G(千兆)。 因此,此代码在最新的编译器(例如gcc(在Linux下)或Visual Studio(在Windows下))中应该可以正常工作。 尝试切换到这些编译器。 它们非常好,如今已被广泛使用。 16位编译器已过时。 避免使用此类编译器。 如果您使用的是Windows,则代码块或dev c ++是一些学习c的良好编程IDE。

PS避免使用%u来打印地址。 请改用%p。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM