指针总结
基础概念
系统给虚拟内存的每个存储单元分配了一个编号,0x0000 0000-0xff ff ff ff,这个编号是地址,指针就是地址
内存数据的访问方式:
(1)直接访问—按变量名存取变量。
(2)间接访问——将变量的地址存放在另一个变量(指针变量),通过指针变量来访问。
数据在内存中的地址也称为指针,如果一个变量存储了一份数据的指针,我们就称它为指针变量。
在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。指针变量的值就是某份数据的地址,这样的一份数据可以是数组、字符串、函数,也可以是另外的一个普通变量或指针变量。
在32位平台,地址总线是32位,地址是32位编号,所以指针变量是32位即4个字节
注意:
(1)无论什么类型的地址,都是存储单元的编号,在32位平台下都是4个字节
即任何类型的指针变量都是4个字节大小.在64位系统中任何类型的指针都是8个字节大小。
(2)对应类型的指针变量,只能存放对应类型的变量的地址
举例:整型的指针变量,只能存放整型变量的地址
拓展:
字符变量char ch=’b’;ch占一个字节,它有一个地址编号,而这个编号就是ch的地址
整型变量int a=0x12345678;a占4个字节,它占4个字节的存储单元,有4个地址编号
指针的定义及赋值方法
指针变量同普通变量一样,使用之前不仅要定义说明,而且必须赋予具体的值。未经赋值的指针变量不能使用, 否则将造成系统混乱,甚至死机。指针变量的赋值只能赋予地址, 决不能赋予任何其它数据,否则将引起错误。
1.简单的指针变量
数据类型 * 指针变量名;
int * p;//定义了一个指针变量p
注意:在定义指针变量的时候 * 是用来修饰变量的,说明变量p是个指针变量。
变量名是p
2.关于指针的运算符
&取地址、*取值(解引用)
int pa = &a; 也可以写成 int pa = &a; 即 * 号可以紧跟在变量类型后,也可以紧跟在变量名字前,就是个指针类型标识符。这条语句等价于 int *pa; pa=&a;
其具体含义为:定义一个可以指向整型数据的指针变量pa,并用整型变量a的地址值对指针变量pa进行初始化,从而使指针变量pa具体地指向了整型变量a。
int a=0x12345678;
int b;
int *p;//在定义指针变量的时候*代表修饰的意思,修饰p是个指针变量
p=&a;//把a的地址给p赋值 &是取地址符
b=*p;//这里的*是解引用,取指针p所指向的变量a的值
p保存了a的地址,也可以说p指向了a
p和a的关系分析:
a的值是0x12345678,假设a的地址是:0xbf e8 98 68
int num;
num=*p;
分析:(1)在调用的时候*代表取值的意思,*p就相当于p指向的变量a
(2)即num=*p和num=a是等价的
(3)所以num=0x12345678;
小拓展:如果在一行中定义多个指针变量,每个指针变量前面都需要加*来修饰
? int *p,*q;//定义了两个整型的指针变量p和q
? int *p,q;//定义了一个整型指针变量p,和整型变量q
指针变量的运算(引用)
指针变量可以进行某些运算,但其运算的种类是有限的。 它只能进行赋值运算和部分算术运算及关系运算。
1指针运算符
指针运算符
(1)取地址运算符 &
?&是单目运算符,其结合性为自右至左,其功能是取变量的地址。例&a即变量a的地址
(2)取内容运算符 *
?*是单目运算符,其结合性为自右至左,用来表示指针变量所指的变量。在*运算符之后跟的变量必须是指针变量。
注意:指针运算符*和指针变量说明中的指针说明符* 不是一回事。
在指针变量说明中,“*”是类型说明符,表示其后的变量是指针类型。int *p;
而表达式中出现的“*”则是一个运算符用以表示指针变量所指的变量。*p=&a
若有定义: int a, p=&a
(1)&*p 表示:p
(2)*&a 表示: a
(3)(*p)++相当于a++
(4)*p++相当于*(p++),即先取p所指向变量的值,然后,让p指向下一个存储单元。
(5)*++p相当于*(++p),即先让p指向下一个存储单元,然后再取p所指向变量的值。
//利用指针输入变量的值
main()
{ int a,b;
int *p;
p=&a;
scanf("%d",p);
p=&b;
scanf("%d",p);
printf(”a=%d, b=%d\n",a,b);
}
2指针变量的赋值运算
指针变量的赋值运算有以下几种形式:
1.指针变量初始化赋值,前面已作介绍。
2.把一个变量的地址赋予指向相同数据类型的指针变量。
例如: int a,*pa;
pa=&a; /*把整型变量a的地址赋予整型指针变量pa*/
3.把一个指针变量的值赋予指向相同类型变量的另一个指针变量。
如: int a,*pa=&a,*pb;
pb=pa;
把a的地址赋予指针变量pb,
由于pa,pb均为指向整型变量的指针变量,
因此可以相互赋值
4.把数组的首地址赋予指向数组的指针变量。
例如: int a[5],*pa;
pa=a; (C语言规定数组名表示数组的首地址)
也可写为: pa=&a[0];
数组第一个元素的地址也是整个数组的首地址,也可赋予pa
当然也可采取初始化赋值的方法:
int a[5],*pa=a;
5.把字符串的首地址赋予指向字符类型的指针变量。
例如: char *pc;
pc="C language";
或用初始化赋值的方法写为:
char *pc="C Language";
这里应说明的是并不是把整个字符串装入指针变量, 而是把存放该字符串的字符数组的首地址装入指针变量。
注意:指针变量可以赋予0值,则p=0表明p是空指针,它不指向任何变量;
字符串的地址和指向字符串的指针变量
字符串在内存中的起始地址称为字符串的地址,可以定义一个字符指针变量指向一个字符串。
1.逐个引用
main()
{
char *string=”I love Beijing.”;
for(; *string!=’\0’; string++)
printf(“%c”, *string);
printf(“\n”);
}
字符指针变量string中,仅存储串常量的地址,而串常量的内容(即字符串本身),是存储在由系统自动开辟的内存块中,并在串尾添加一个结束标志’\0’。
2.整体引用
main()
{ char *string=”I love Beijing.”;
printf(“%s\n”,string);
}
通过指向字符串的指针变量string,整体引用它所指向的字符串的原理:系统首先输出string指向的第一个字符,然后使string自动加1,使之指向下一个字符;重复上述过程,直至遇到字符串结束标志。
3.字符指针变量与字符数组之比较
虽然用字符指针变量和字符数组都能实现字符串的存储和处理,但二者是有区别的,不能混为一谈。
(1)存储内容不同。
字符指针变量中存储的是字符串的首地址