上一页 下一个

C编程的基础知识

指针:理解内存地址

f的变量使用四字节的RAM在内存中。这个位置有一个特定的地址,在这种情况下,248440年。”width=
f的变量使用四字节的RAM在内存中。这个位置有一个特定的地址,在这种情况下,248440年。
©2011 H18新利最新登入owStuffWorks.com

前面的讨论变得有点清楚如果你了解内存地址在计算机的硬件工作。18新利最新登入如果你还没有读过,现在是一个很好的时间来阅读18新利最新登入比特和字节是如何工作的完全理解比特、字节和单词。

所有电脑都内存,也被称为内存(随机存取存储器)。例如,你的电脑可能安装了16或32或64 mb的RAM。内存保存你的电脑目前正在运行的程序以及他们目前的数据操纵(他们的变量和数据结构)。记忆可以被认为仅仅是一个字节数组。在这个数组,每一个内存位置都有自己的地址,第一个字节的地址是0,紧随其后的是1,2,3,等等。内存地址的行为就像一个正常的数组的索引。电脑可以随时访问任何地址在内存中(因此得名“随机存取存储器”)。它也可以字节分组需要形成较大的变量、数组和结构。例如,一个浮点变量4连续的字节内存消耗。你可能会使全球声明以下程序:

广告

浮动f;

这个声明中说,“声明一个位置命名f可以装一个浮点值。”When the program runs, the computer reserves space for the variablef在内存中。这个位置有一个固定地址的内存空间,像这样:

虽然你认为变量f认为,计算机内存中的一个特定的地址(例如,248440)。因此,当您创建一个声明如下:

f = 3.14;

编译器可能会翻译成,“价值3.14加载到内存位置248440。”The computer is always thinking of memory in terms of addresses and values at those addresses.

顺便说一下,有几个有趣的副作用你电脑对待记忆的方式。例如,说你下面的代码包含在一个程序:

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

你看到的输出程序可能看起来像这样:

s: t 1:5 2:2三3 4:4 5 u = 5

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

数组放置彼此相邻”width=
数组放置彼此相邻

因此,当你试着写s[4],它不存在,系统写t[0]而不是因为t[0]是[4]应该。当你写进t[4],你真的写进u。计算机而言,[4]是一个地址,它可以写进去。然而,正如您所看到的即使计算机18新利最新登入执行程序,它是不正确的或有效的。该项目腐败数组t在运行的过程中。如果你执行下面的语句,更严重后果的结果:

s [1000000] = 5;

的位置年代(1000000)以外的更有可能是你的程序的内存空间。换句话说,你在写程序到内存中,并不是自己的。与保护系统内存空间(UNIX、Windows 98 / NT),这类语句将导致系统终止程序的执行。在其他系统上(Windows 3.1, Mac),然而,系统并没有意识到自己在做什18新利最新登入么。你最终损害或变量在另一个应用程序的代码。违反的影响的范围可以从一无所有到一个完整的系统崩溃。在内存中,我,s t和u都是放在旁边,另一个在特定的地址。因此,如果你写过去的变量的边界,电脑会做你所说的,但最终会破坏另一个内存位置。

因为C和c++不执行任何形式的范围检查当你访问一个元素的数组,至关重要的是,你,作为一个程序员,注意数组范围自己和保持在数组的适当的边界。无意中读或写数组边界之外总是导致错误的程序行为。

另外一个例子,试试以下:

# include < stdio。h > int main () {int i, j。int * p;/ *整数指针* / printf (" % d % d \ n”, p,我);p =我;printf (% d % d \ n, p,我);返回0;}

这段代码告诉编译器输出的地址p和地址我。的变量p开始与一些疯狂的价值或0。的地址通常是一个较大的值。例如,当我跑这段代码,我得到以下输出:

0 2147478276 2147478276 2147478276

这意味着的地址吗是2147478276。一旦声明p =我;已经执行,p包含的地址。试试这个:

# include < stdio。h > void main () {int * p;/ *整数指针* / printf (" % d \ n”, * p);}

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

说,我们现在可以看指针在一个全新的视角。以这个项目为例:

# include < stdio。h > int main () {int我;int * p;/ *整数指针* / p =我;* p = 5;printf (" % d % d \ n”,我,* p);返回0;}

这是发生了什么:

的变量消耗4个字节的内存。指针p也消耗4字节(在大部分机器在今天使用,消耗4字节的内存的指针。在大多数内存地址是32位长cpu今天,虽然有一个上升趋势64位寻址)。我都有一个特定的地址的位置,在这种情况下,248440年。指针p认为,一旦你说地址p =我;。的变量* p因此是等价的。

的指针p字面上的地址。当你说这样一个程序:

printf (" % d”, p);

出来的是变量的实际地址

特色
Baidu