文档库 最新最全的文档下载
当前位置:文档库 › C语言指针详解

C语言指针详解

C语言指针详解
C语言指针详解

C语言指针详解

1 程序如何运行

当我们打开电脑中的任何一个程序运行时,我们的操作系统会将该程序存在硬盘的所有数据装载到内存中,然后有CPU 进行读取内存中的数据并进行计算,并将计算的结果返回给我们的操作系统,然后操作系统将相应的动作交付给相应的硬件来完成。如:将声音数据交给声卡,最后有音响输出来,将图像交给显卡最后有显示器输出……

但是还会有一部分数据会返回给内存,以供程序下面的语句继续使用。

我们都知道内存的容量有很大,如:4G,8G, 16G,有时候我们会打开很多的程序,所有的程序的数据都存放到我们的内存中,那么CPU是如何正确的读取我们的不同程序的数据并加以计算的哪?

2 内存的假设设计

为了让我们的CPU 可以很好的读取内存中的数据,内存必须做优化设计,于是给内存设定了集合设计,将我们的内存分成很多大小相同的方格(盒子),所有的数据将放入这些小盒子中,将不同的程序的数据放入到不同的小盒子中,这样就出现的模块化的内存,当我执行程序的一个命令时,CPU就会从相应的盒子读数据然后计算,由于我们硬件所能访问或计算的最小单位是字节,所以内存中的这样的一个小盒子的大小就给他规定一个字节。

3 地址和指针

一般我们声明一块内存空间的时候,会给他取一个名字,为的是我们在编写程序的时候方便使用空间中存放的值,但是CPU 读数据的时候会忽视这个名字,因为CPU无法理解这样的数据,CPU 只能执行0,1代码,那么CPU是如何知道从什么地方读取数据,又到什么地方地址数据的读取的那,所以必须对内存做2次设计,就是将内存中分成的很多小盒子下面标注一些顺序的序号,例如:从第一个盒子开始,标注1,2,3,4,5,6,7,……每一个数字

对应一个盒子,但是真正的内存如中不是使用这些十进制数字的,而是使用16进制整数表示的,如0x16ffee。这些我们标记的数字就叫做内存中的地址。由于这些地址和盒子是对应的关系,所以只要知道了地址,就可以得到对应盒子中存放的数据了,形象的说,我们说这个地址指向对应的盒子,在C语言中可以通过地址得到对应盒子的数据是*地址。所以在程序中,我们只要通过这个地址告诉CPU,从哪个地址读取数据,然后读几个字节(也就是几个小盒子的数据),CPU就能正确的读取数据了。

由于知道了地址,就可以知道对应地址的内存空间数据,并且他们用一种形象的指向去表示这种关系,于是我们就有了地址就是指针的说法。(指针更能表示这种关系)

4 内存中的对象和指针变量

我们在写程序的时候很多数据占用大于一个字节的数据的时候,一个小盒子已经无法满足需求,这是我们将通过内存中连续的小盒子进行存贮数据,那么这个数据就会占用一块的内存空间,我们称这块内存就是内存中的一个对象实例,这个时候这块内存将会对应很多的地址,我们如何表示这块的内存的地址那,当我们的数据大于一个字节的时候,通常会采用首地址(即第一个字节的地址)来表示这个对象的地址。以后我们会遇到一个指针指向一个变量,说的就是这个指针指向这块内存的首地址(记住指针只是一个地址)。

不同类型的变量是存放不同数据的,如int 变量是放整形数据,浮点变量是放浮点数据的,字符变量是存放字符数据的。那么存放地址的变量,我们就叫他地址变量,即指针变量,编程中,我们所说的指针就是指指针变量。指针变量的值就是他所指向的那个对象的第一个字节的地址,对指针变量运用运算符*,就可以得到他所指向的那个对象的数据。

5 指针和普通类型的关系

& 运算符:获取内存对象实例的地址。

* 运算符:通过对象的地址获取对象中的数据

我们可以获取到普通类型对象的地址,然后赋值给相同类型的指针变量。因为通过对象的首地址就可以找到这个变量,而指针变量可以保存某个对象的首地址,所以这个指针就指向了此时的对象,就可以通过指针来操作此对象的数据了。

对于普通类型的对象,我们可以通过指向该对象的指针运用*,来获取该对象的值进行操作,我们还可以,把指针的值,赋值给另一个指针变量,此时2个指针指向同一个对象。

但是当指针指向普通的类型,不可以运用+,-或>, <, == 运算符,因为此时没有任何的意义。

我们还可以对指针变量运用&运算符来获取指针变量在内存中的地址,这就是指针的指针,即2级指针,2级指针相对比较复杂,我们暂时不去研究。

6 指针和一维数组

进入正题之前我们先来看下:什么是指针常量和什么是常量指针

指针常量:一旦指针指向的对象赋予了一个值,那么将无法在通过指针修改所指针的对象中的数值,即指针所指向的数据是一个常量,无法在修改。但是可以让指针指向别的对象。如:

Int a = 10;

const int * p = &a;

这个时候不可以通过*p 在修改a对象中的数据了。此时const 修饰的是int,即p 指向的是一个常量,常量的值是不可以改变的;

常量指针:一个指针变量指向内存中一个对象的时候,如果无法让该指针指向其他的对象。那么该指针就是常量指针,即该指针是一个常量(此时类似于一个内存中的地址,无法改变),但是可以修改该指针所指向的对象中的数据。

如:

Int a = 10;

Int b = 20;

Int * const p = &a;

此时const修饰的是p。就是无法在改变p的值,而p 是一个指针,可以保存一个地址,所以p 可以在初始化的时候保存一个对象的地址,如果在让别的地址赋值给p,就会出错。

当我们声明一个数组的时候,那么数组的名字就是这个对象的地址,(即数据名就是对象中第一个字节所对应的地址也就是说数组名就是第一个元素的地址)我们操作数组中的元素的时候,都会从数组的首地址开始,然后到对应元素的地址开始读取数据,根据数组的类型,读取几个字节取出数据。其实这就是指针的操作。此时的数组名是一个常量指针。我们知道数组名其实就是一个地址,可以用来进行计算(当2个指针指向同一块连续的内存空间的时候,可以运用指针的算术运算和关系运算如数组),但是无法修改数组的首地址。

我们可以把数组的地址赋值给指针,让该指针指向数组对象,此时就可以通过指针来操作数组了。如数组元素array【3】,等于*(array + 3),意思是从array这个地址开始,移动3个元素,(移动后的结果也是一个地址即指针),然后取出对应对象中的数据。

6 指针和二维数组(待续……)

7 指针和字符串(难)(待续……)

8 指针和结构体(待续……)

9 指针和函数(待续)

10 单链表的实现(待续……)

以上知识点将通过视频讲解,望到时观看。

总结:如果对指针的理解不够深入的话,运用指针很容易出错,切很难找到问题。

所以一般不通过指针就可以解决的尽量不要使用指针。但有时候必须使用指针才能解决就无法避免了。那么究竟指针的用处在什么地方那(留给读者思考下)

相关文档