上一页 下一个

C语言编程基础

指针:理解内存地址

变量f在内存中消耗4个字节的RAM。该位置有一个特定的地址,在本例中为248,440。"width=
变量f在内存中消耗4个字节的RAM。该位置有一个特定的地址,在本例中为248,440。
©2011 H18新利最新登入owStuffWorks.com

如果您了解内存地址在计算机硬件中的工作原理,前面的讨论就会更清楚一些。18新利最新登入如果你还没有读过这本书,现在是时候读了18新利最新登入比特和字节是如何工作的完全理解比特、字节和单词。

所有电脑都有内存,也被称为内存随机存取存储器).例如,您的计算机现在可能安装了16兆、32兆或64兆的RAM。RAM保存计算机当前正在运行的程序以及它们正在操作的数据(它们的变量和数据结构)。内存可以简单地认为是一个字节数组。在这个数组中,每个内存位置都有自己的地址——第一个字节的地址是0,然后是1、2、3,等等。内存地址就像普通数组的索引一样。计算机可以在任何时间访问内存中的任何地址(因此得名“随机存储器”)。它还可以根据需要将字节分组在一起,以形成更大的变量、数组和结构。例如,一个浮点变量在内存中消耗4个连续的字节。你可以在程序中做如下的全局声明:

广告

浮动f;

这个语句说,“声明一个名为f它可以容纳一个浮点值。”当程序运行时,计算机为变量预留空间f在记忆的某处。该位置在内存空间中有一个固定的地址,就像这样:

当你考虑变量时f时,计算机会在内存中考虑一个特定的地址(例如248,440)。因此,当你创建这样的语句时:

F = 3.14;

编译器可能会将其转换为“将值3.14加载到内存位置248,440中。”计算机总是根据地址和这些地址的值来考虑内存。

顺便说一下,计算机处理内存的方式有几个有趣的副作用。例如,假设你在一个程序中包含以下代码:

Int i, s[4], t[4], u=0;(我= 0;我< = 4;I ++) {s[I] = I;t[我]=我;} printf (" s: t \ n ");(我= 0;我< = 4;I ++) printf("%d:%d\n", s[I], t[I]);Printf ("u = %d\n", u);

你从程序中看到的输出可能是这样的:

S:t 1:5 2:2 3:3 4:4 5:5 u = 5

为什么t [0]而且u不正确的?如果仔细查看代码,可以看到for循环将每个数组的末尾后面写入一个元素。在内存中,数组彼此相邻,如下所示:18新利最新登入

彼此相邻放置的数组"width=
彼此相邻放置的数组

因此,当你试图写入不存在的s[4]时,系统会改为写入t[0],因为t[0]是s[4]应该在的位置。当你向t[4]写入时,你实际上是在向u写入。就计算机而言,s[4]只是一个地址,它可以向它写入。然而,正如你所看到的,即使计算18新利最新登入机执行了程序,它也不是正确或有效的。程序在运行过程中破坏了数组t。如果执行以下语句,将导致更严重的后果:

S [1000000] = 5;

的位置年代(1000000)很可能超出了程序的内存空间。换句话说,您正在写入程序不拥有的内存。在具有受保护内存空间的系统上(UNIX、Windows 98/NT),这类语句将导致系统终止程序的执行。然而,在其他系统(Windows 3.1、Mac)上,系统并不知道你在做什么。18新利最新登入您最终会破坏另一个应用程序中的代码或变量。违规的影响可以从什么都没有到完全的系统崩溃。在内存中,i、s、t和u都被放在一个特定的地址旁边。因此,如果你写的内容超过了一个变量的边界,计算机会按照你说的去做,但它最终会破坏另一个内存位置。

由于C和c++在访问数组的元素时不执行任何类型的范围检查,因此作为程序员,必须仔细注意这一点数组范围并保持在数组的适当边界内。在数组边界之外无意地读取或写入总是会导致错误的程序行为。

作为另一个例子,试试下面的方法:

#include  int main() {int i,j;int * p;/*指向整数的指针*/ printf("%d %d\n", p, &i);P = &i;Printf ("%d %d\n", p, &i);返回0;}

这段代码告诉编译器打印保存的地址p,并附上地址我。的变量p从一个疯狂的值或者0开始。地址:通常是一个较大的值。例如,当我运行这段代码时,我收到以下输出:

0 2147478276 2147478276 2147478276

也就是说…的地址是2147478276。一旦声明P = &i;已经执行了,p包含.你也可以试试这个:

#include  void main() {int *p;/*指向整数的指针*/ printf("%d\n",*p);}

这段代码告诉编译器打印p点。18新利最新登入然而,p尚未初始化;它包含地址0或一些随机地址。在大多数情况下,a段错误(或其他一些运行时错误)结果,这意味着您使用了指向无效内存区域的指针。几乎总是,未初始化的指针或错误的指针地址是导致分段错误的原因。

说了这么多,我们现在可以从一个全新的角度来看待指针。以这个程序为例:

#include  int main() {int i;int * p;/*指向整数的指针*/ p = &i;* p = 5;Printf ("%d %d\n", i, *p);返回0;}

事情是这样的:

的变量占用4字节内存。指针p也消耗4个字节(在目前使用的大多数机器上,一个指针消耗4个字节的内存。内存地址最多是32位长cpu今天,尽管64位寻址的趋势越来越大)。i的位置有一个特定的地址,在本例中为248,440。指针p保存着你说的那个地址P = &i;.的变量* p而且因此是等价的。

的指针p的地址.当你在节目中说这样的话:

printf (" % d”,p);

结果是变量的实际地址

特色
Baidu