C语言之指针
C语言之指针
山林川泽地址
何谓地址?在内存(注意:我们这里提到的内存并不是人们常说的计算机的物理内存,而是虚拟的逻辑内存空间)中,简单地说:地址就是可以唯一标识某一点的一个编号,即一个数字!我们都见过尺子,我们统一以毫米为单位,一把长1000毫米的尺子,其范围区间为0~999,而我们可以准确的找到35毫米、256毫米处的位置。
同样的道理,内存也是如此,像尺子一样线性排布,只不过这个范围远远大于尺子,在32位操作系统下,这个范围是0-4,294,967,295而地址就是这之中的一个编号而已,习惯上,在计算机里地址我们常常用其对应的十六进制数来表示,比如0x12ff7c这样。在我们的C程序中,每一个定义的变量,在内存中都占有一个内存单元,比如int类型占四个字节,char类型占一个字节等等,每个字节都位于0-294,967,295之间都有一个对应的编号,C语言允许在程序中使用变量的地址,并可以通过地址运算符 ”&“ 得到变量的地址
例如
1 | #include<stdio.h> |
指针
明白地址的概念之后,指针也就不奇怪了。简单地讲,地址就是逻辑内存上的编号,而指针虽然也表示一个编号,也是一个地址。但两者性质却不相同。一个代表了常量,另一个则是变量。就好比内存是一把尺子,而指针就是尺子上面的游标,可以左右移动,它某一个时刻是指向一个地方的,这就是指针变量。
对指针变量定义的一般形式为:
类型说明符 *变量名;
其中,这里的与前面的类型说明符共同说明这是一个指针变量,类型说明符表示该指针变量所指向的变量为何种数据类型,变量名即为定义的指针变量名。除此之外,C还提供运算符获取地址上对应的值,例如:
1 | #include<stdio.h> |
我们已经知道,通过数组下标可以确定数组元素在数组中的顺序和存储地址。由于每个数组元素相当于一个变量,因此指针变量可以指向数组中的元素,也就是说可以用指针方式访问数组中的元素。
对一个指向数组元素的指针变量的定义和赋值方法,与指针变量相同,例如:
1 | int a[10];/*定义a为包含10个整型数据的数组*/ |
C语言规定,数组名代表数组的首地址,也就是第0号元素的地址。因此:
1 | p=a; /*等价于p=&a[0];*/ |
对于指向 首地址(a[0]) 的指针p,p+i(或a+i)就是数组元素**a[i]的地址,(p+i)( 或(a+i) )就是a[i]的值。
如果指针变量p已指向数组中的某一个元素,则p+1指向同一数组中的下一个元素。
引入指针变量后,就可以用以下两种方法来访问数组元素:
(1)下标法,即用a[i]形式访问数组元素,在前面介绍数组时都是采用这种方法。
(2)指针法,即采用*(a+i)或*(p+i)形式,用间接访问的方法来访问数组元素,其中a是数组名,p是指向数组的指针变量,其初值p=a。
1 | #include<stdio.h> |
注意输出的两种方式,指针可以通过++或–并修改自身值的方式移动,然而数组名本身值不可以被更改。
前面我们已经讨论过字符数组与字符串,字符指针也可以指向一个字符串,可以用字符串常量对字符指针进行初始化,例如:
1 | char *str = "shanlinchuanze,github,io" ; |
这是对字符指针进行初始化。此时,字符指针指向一个字符串常量的首地址。
还可以用字符数组来存放字符串,例如:
1 | char string[ ] = "shanlinchuanze,github,io"; |
在这个语句中,string是数组名,代表字符数组的首地址。因此可以通过数组名string来访问字符串。
字符串指针和字符串数组两种方式都可以访问字符串,但它们有着本质的区别:字符指针str是个变量,可以改变str使它指向不同的字符串,但不能改变str所指向的字符串常量的值。而string是一个数组,可以改变数组中保存的内容。应注意字符串指针和字符串数组的区别。