目录
一、指针简介
为说明指针,就需知道数据在内存中是如何存储的。
在计算机内存中,是以字节(byte)为存储单元的,而每个单元都有相应的编号,即地址。
打个比方:点外卖的时候,需要填写你收货的地址,比如说你的房号是2001,而这个房号2001就是地址,或者说,2001指向该房间,而将地址形象地称为“指针”,外卖员通过这个就可以精准的送外卖到你手上。在计算机中,通过指针就可以找到以指针为地址的内存单元。
换句话说,指针就是内存单元的地址。(实在傻傻分不清,认为指针就是地址就可以了)
例如:在程序中定义了一个整型变量k;
int a;
在程序编译的时候,计算机就会自动为变量k匹配一个4个字节的内存空间。如下图所示
(一个格子代表一个字节的存储空间)。
在图中,a有一个地址0x100,要想在程序中把它记录下来,就需要定义一个整型变量去存储。而在C语言当中,规定了用指针变量去存储
指针变量的定义:
①一般形式: <数据类型> *<指针变量名>
例如:
int *p;//定义指针变量p
p = &a;//把a的地址赋值给指针变量p
int* 可以看作是指向整型变量的指针类型。
②也可以在定义指针变量时,同时给它初始化。
例如:
int *p = &a;
注意:(1)指针变量前面的“ * ”是不可省略的,指针变量名是p,而不是*p,“ * ”是为了说明这是一个指针变量。
(2)在定义指针变量时,必须指定基类型,即指针要指向存储单元存储的数据类型,不然程序会报错,例如:
//正确定义:
int a;
int *p = &a;//p声明的数据类型要与变量a相同,同为整型
//错误定义:
char a;
int *p = &a;
(3)指针变量只能存储地址,不能把一个整数赋给一个指针变量。
(4)在32位的环境里,任何指针的长度都是4个字节;在64位的环境里,任何指针的长度都是8个字节。C语言当中,求变量长度,用sizeof(函数),如
printf("%d\n", sizeof(int*));
printf("%d\n", sizeof(char*));
printf("%d\n", sizeof(short*));
printf("%d\n", sizeof(long*));
printf("%d\n", sizeof(float*));
printf("%d\n", sizeof(double*));
运行结果:
(本人所用到的环境是32位的,所以指针变量的长度都为4个字节。)
(5)取地址时,无论变量占多少个字节,指针取的一定是该变量的首地址。
一个变量的指针有两层含义:一是一存储单元编号表示的地址,二是它指向的存储单元的数据类型。
二、指针变量的引用
熟悉两个与指针相关的运算符
(1)& 取地址运算符。&a是变量a的地址。
(2)* 指针运算符,有两种含义:
①*定义的时候,前面是数据类型,中间是“*”,后面是指针变量名。
②*p代表取p指向内存空间下存储的数据。(即取值)
int *p = &a;
*p就是整型变量a的值
三、指针的运算
指针运算是以指针所存储的值(即地址)作为运算量进行的运算,实质就是地址的计算。
(1)指针的算术运算
p+n,往地址大的方向移动了n个字节单元
p++,相当于指针p向地址大的方向移动1个字节单元
p--,相当于指针p向地址小的方向移动1个字节单元
注意:不同数据类型的两个指针进行加减运算是无效的。
px+n的实际内存单元的地址量:(px)+sizeof(px的数据类型)*n。
px-n的实际内存单元的地址量:(px)-sizeof(px的数据类型)*n。
两指针相减的结果是两指针相隔的数据个数,而不是两指针的值相减的结果,
公式:(q-p)/类型字节长度
如
#include <stdio.h>
int main()
{
int a[5] = {1,2,3,4,5};
int *p, *q;
p = &a[0];
q = &a[3];
printf("%p %p\n", p, q);
printf("%d %d\n", *p, *q);//打印p和q指向存储空间里的内容
printf("%d\n", q-p);//求指针q-指针p的值
return 0;
}
运算结果:
(2)指针的关系运算
(3)空指针
这里的空指针,指的是指针变量存了零号地址,即
int *p = 0;
而在C语言中,指针常量只有NULL一个,NULL就是它是用于表明一个指针变量目前没有执行任何对象。
如果没有为指针p初始化,p的指向是不明确的,如果p指向非法地址,后果是无法预测的。把p初始化为空,是一个好习惯。但需要注意的是:不能对空指针进行间接引用。