当考虑指针时,它会有所帮助画图。指针是指向内存中地址的箭头,带有指示值类型的标签。地址表示要查找的位置,类型表示要获取的内容。投射指针会更改箭头上的标签,但不会更改箭头所指的位置。
d
in main
是一个指向c
这是类型char
. A char
是一个字节的内存,所以当d
取消引用后,您将获得该内存字节中的值。在下图中,每个单元代表一个字节。
-+----+----+----+----+----+----+-
| | c | | | | |
-+----+----+----+----+----+----+-
^~~~
| char
d
当你施放时d
to int*
,你是说d
确实指向一个int
价值。在当今的大多数系统上,int
占用4个字节。
-+----+----+----+----+----+----+-
| | c | ?₁ | ?₂ | ?₃ | |
-+----+----+----+----+----+----+-
^~~~~~~~~~~~~~~~~~~
| int
(int*)d
当您取消引用时(int*)d
,您将获得由这四个字节的内存确定的值。您获得的值取决于这些标记的单元格中的内容?
,以及如何int
被表示在内存中。
A PC is 小尾数法 http://en.wikipedia.org/wiki/Endianness,这意味着 a 的值int
是这样计算的(假设它跨越4个字节):* ((int*)d) == c + ?₁ * 2⁸ + ?₂ * 2¹⁶ + ?₃ * 2²⁴
。所以你会看到,虽然该值是垃圾,但如果你以十六进制打印(printf("%x\n", *n)
),最后两位数字始终是35
(这就是角色的价值'5'
).
其他一些系统是大尾数并以另一个方向排列字节:* ((int*)d) == c * 2²⁴ + ?₁ * 2¹⁶ + ?₂ * 2⁸ + ?₃
。在这些系统上,您会发现该值始终starts with 35
以十六进制打印时。有些系统的大小为int
这与 4 字节不同。很少有系统安排int
以不同的方式,但你极不可能遇到它们。
根据您的编译器和操作系统,您可能会发现每次运行程序时该值都不同,或者它始终相同,但当您对源代码进行细微调整时会发生变化。
在某些系统上,int
值必须存储在 4(或 2、或 8)的倍数的地址中。这被称为结盟 http://en.wikipedia.org/wiki/Data_structure_alignment要求。取决于地址是否c
无论是否正确对齐,程序都可能崩溃。
与您的程序相反,当您有一个int
值并获取指向它的指针。
int x = 42;
int *p = &x;
-+----+----+----+----+----+----+-
| | x | |
-+----+----+----+----+----+----+-
^~~~~~~~~~~~~~~~~~~
| int
p
指针p
指向一个int
价值。箭头上的标签正确描述了内存单元中的内容,因此取消引用它时不会出现任何意外。