简体   繁体   English

打印指针变量的地址

[英]printing the address of a pointer variable

I have learnt that while printing the address of a variable in c, we use unsigned int ( %u in format string). 我了解到,在c中打印变量的地址时,我们使用unsigned int(格式字符串中的%u )。
Its range is from 0 to 65535. Now an integer takes 4 bytes of memory, which means a maximum of 16384 (65536/4) integers can be stored. 其范围是从0到65535。现在一个整数占用4个字节的内存,这意味着最多可以存储16384(65536/4)个整数。 What will happen if we try to declare an array int a[20000] and get addresses of each of its element? 如果我们尝试声明一个数组int a[20000]并获取其每个元素的地址,将会发生什么?

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

In early times of C, a pointer and a int where similar types, and you could safely cast from one to the other and back again. 在C的早期,一个指针和一个int类型相似,并且您可以安全地从一个指针转换为另一个指针,然后再次返回。 In that early time, pointers and int were both 16 bits long. 在那个早期,指针和整数都长16位。 It is still true on 32 bits systems where int is now 32 bits. 在int现在为32位的32位系统上,这仍然是正确的。 But it is false on 64 bits systems, because pointers are 64 bits long and int only 32 bits. 但这在64位系统上是错误的,因为指针的长度为64位,而int仅为32位。

So I do not know where and how you learnt that while printing the address of a variable in c , we use unsigned int(%u) , but forget it ASAP because in the general case it is wrong . 所以我不知道您在哪里以及如何得知在c中打印变量的地址时,我们使用unsigned int(%u) ,但会尽快将其忘记,因为通常情况下这是错误的 The only foolproof way to print an adress is %p because system automatically adapt the size to 16, 32 or 64 bits. 打印地址的唯一简单方法是%p因为系统会自动将大小调整为16、32或64位。

And no longer convert pointers to int or opposite side, because it is highly non portable. 并且不再将指针转换为int或相反侧,因为它高度不可移植。 From that other post , A more portable way (on the C99 standard variant) is to #include <stdint.h> and then cast pointers to intptr_t (and back). 在另一篇 文章中一种更可移植的方式(在C99标准变体上)是#include <stdint.h> ,然后将指针转换为intptr_t (然后返回)。 This integer type is guaranteed to be the size of a pointer. 保证此整数类型为指针的大小。

And, I almost forgot 65536 = 0x10000 = 2 16 , and 2 32 = 4294967296. So you were not that far from reality, and it is true that in older 16 bits system you could not have int array[40000] because int were 16 bits long and the array would exhaust all the available memory. 而且,我几乎忘记了65536 = 0x10000 = 2 16和2 32 =4294967296。因此,您与现实相距不远,而且的确如此,在较旧的16位系统中,您无法使用int array[40000]因为int为16位长,数组将耗尽所有可用内存。

But on 32 bits systems, you can address 4 Gb of memory, so int array[20000] is harmless. 但是在32位系统上,您可以寻址4 Gb的内存,因此int array[20000]是无害的。

A pointer is a memory address where you can find some data. 指针是一个内存地址,您可以在其中找到一些数据。 We can find the size the of a pointer variable using sizeof( ) operator. 我们可以使用sizeof()运算符找到指针变量的size。 So its size doesn't depend on what it points at .It however depends on many bytes a memory address takes up on your system, which is 4 for a 32 bit compilers and 8 for 64-bit compiler. 因此它的大小不取决于它指向的内容,而是取决于系统上占用的内存地址的多个字节,对于32位编译器为4,对于64位编译器为8。

If we have declared a pointer, double j, type of j is double , ie “a pointer to double". 如果我们声明了一个指针double j,则j的类型为double ,即“指向double的指针”。

%p is the correct format specifier for printing a pointer. %p是用于打印指针的正确格式说明符。 %p outputs addresses in the hexadecimal notation. %p以十六进制表示形式输出地址。

Sometimes people use %u and %x (unsigned int in hexadecimal form) specifiers to print a pointer variable. 有时人们使用%u和%x(十六进制形式的无符号int)说明符来打印指针变量。 It is however an undefined behavior to pass a pointer for a %x or %u argument. 但是,为%x或%u参数传递指针是未定义的行为。

However it works with 32 bit compilers like code blocks .This is because the size of unsigned int and the pointer is same here. 但是它可以与32位编译器(如代码块)一起使用,这是因为unsigned int和指针的大小在此处相同。 (Both 4 bytes) (两个字节)

(It is false to assume that int and pointers have the same width . For both GCC 64 bit and MSVC 64 bit running on x64, sizeof(void *) == 8, while sizeof(unsigned int) == 4. It just so happens that on some architectures pointers and ints are the same size, eg the PDP-11/34a, or most 32 bit architectures nowadays. But it is extremely unwise to ever write code that relies on it. (假设int和指针具有相同的宽度是错误的。对于在x64上运行的GCC 64位和MSVC 64位,sizeof(void *)== 8,而sizeof(unsigned int)== 4。碰巧在某些架构上,指针和整数的大小相同,例如PDP-11 / 34a或当今的大多数32位架构,但是编写依赖于它的代码是极其不明智的。

You can do add extra 2 lines as below and verify: 您可以按照以下步骤添加额外的2行并进行验证:

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

On a 64-bit GCC machine with a 64-bit operating system, this should give you 4 and 8 respectively ) 在具有64位操作系统的64位GCC计算机上,这应该分别给您4和8)

On a GCC 64-bit machine-%x casts your pointer to an unsigned integer (32-bit length). 在GCC 64位计算机上,%x将指针转换为无符号整数(32位长度)。 The size of pointer is of 8-byte (64 bit) length. 指针的大小为8字节(64位)。 Printing with %p prints the whole pointer, in its complete size – 64 bits. 使用%p进行打印将以其完整大小(64位)打印整个指针。 But when you are printing with %x, only the lower 32 bits are printed. 但是,当您使用%x打印时,仅低32位被打印。 Hence it is always safe to print a pointer with %p. 因此,使用%p打印指针始终是安全的。

Actually unsigned integers are having range of 0 to 65536 on older 16bit compilers like turbo c. 实际上,在旧的16位编译器(如turbo c)上,无符号整数的范围为0到65536。 Now a days all systems are having 32 or 64 bit architecture on which unsigned integers range is 0 to 4G (giga). 如今,所有系统都具有32或64位架构,其无符号整数范围为0到4G(千兆)。 So this code should work fine in latest compilers like gcc (under linux) or visual studio (under windows). 因此,此代码在最新的编译器(例如gcc(在Linux下)或Visual Studio(在Windows下))中应该可以正常工作。 Try switching to these compilers. 尝试切换到这些编译器。 They are very good and are widely used now a days. 它们非常好,如今已被广泛使用。 16bit compilers are obsolete. 16位编译器已过时。 Avoid using such compilers. 避免使用此类编译器。 If you are using windows then code blocks or dev c++ are some good programming IDEs for learning c. 如果您使用的是Windows,则代码块或dev c ++是一些学习c的良好编程IDE。

PS avoid using %u for printing addresses. PS避免使用%u来打印地址。 Use %p instead. 请改用%p。

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

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