C语言(二)
2020-06-12 本文已影响0人
强某某
指针的概念
- 操作系统给每个存储单元分配了一个编号,从0x00000000~0xffffffff,这个编号就称之为地址,指针就是这个地址
- 指针变量是一个变量,这个变量用来存放一个地址编号,在32位平台下,地址总线是32位的,所以地址是32位编号,即4个字节
- 无论什么类型的地址,都是存储单元的编号,在32位平台下是4个字节,即任何类型的指针变量都是4个字节大小
- 对应类型的指针变量,只能存放对应类型的变量的地址,例如:整型的指针变量,只能存放整型变量的地址
扩展
- 字符变量char ch;ch是一个字节,它有一个地址编号,这个地址编号就是ch的地址
- 整型变量int a;a占4个字节,它占有4个字节的存储单元,有4个地址编号
指针的定义
int a=0x000234f;
int * p;//定义了一个指针变量p
p=&a;//把a的地址给p赋值,&取地址运算符
//*p 就是取出a的值
//p就是a的地址
拓展
- int p,q;//定义了两个整型的指针变量p和q
- int *p,q;//定义了一个整型的指针变量p,和整型的变量q
指针的大小
- 在32位系统下,所有类型的指针都是4个字节;
- 因为不管地址内的空间多大,但是地址编号的长度是一样的,所以32位系统中,地址都是4个
#include <stdio.h>
int main(int argc, char *argv[])
{
char *a;
short *b;
int *c;
long *d;
float *e;
printf("%d\n",sizeof(a)); //4
printf("%d\n",sizeof(b)); //4
printf("%d\n",sizeof(c)); //4
printf("%d\n",sizeof(d)); //4
printf("%d\n",sizeof(e)); //4
return 0;
}
指针++
-
* 指针
形式取值,取几个字节,由指针类型决定的指针为字符指针则取一个字节,为整型则取4个字节,为double则取8个字节 - 指针++指向下个对应类型的数据
- 字符指针++,指向下个字符数据,指针存放的地址编号加1
- 整型指针++,指向下个整型数据,指针存放的地址编号加4
- 注意:此处是指针++,不是指针对应的值加
int a[10];
int *p;
p=a;
p+2;//p是a[0]的地址,P+2是&a[2]
//此处p+2其实是p的值加上int(类型)的字节大小*2
指针和数组元素之间的关系
int a[10];
int *p;
p=a;
p[2]=100;//因为p和a等价,所以a中数据已经被修改
//c中规定,数组的名字就是数组的首地址,即第0个元素的地址,是个常量。p和a不同,p是指针变量,a是常量,所以可以用等号给p赋值,但不能给a赋值
//通过指针运算加取值的方法来引用数组的元素
int a[10];
int *p;
p=a;
*(p+2)=100;//相当于a[2]=100
//解释:p是第0个元素的地址,p+2是a[2]这个元素的地址。对第二个元素的地址取值,即a[2]
指针类型的本质
#include <stdio.h>
int main()
{
int a=0;//假设:变量a的内存地址为123456
&a;
int b=(int)&a;
//&a 值123456 类型:指针 指向int
//b 值123456 类型:整型 指向int
/*
[&a]和[变量b],他们在数值上是一摸一样的,但是他们的类型是不同的
为什么要分为不同的类型呢?
不同的类型,对应着不同使用规则
*b 编译器会报错(*后面应跟着指针类型)
*&a 将[&a]的值解析为地址,然后访问这个地址所对应的内存单元
C语言为什么要引入-》地址运算符&,间接运算符*,指针这种类型?
就是为了让它们互相配合,使我们可以通过地址来访问内存
& 获取一个数值,并将这个数值的类型规定为指针
* 通过指针类型的数值,来访问内存单元
*/
return 0;
}
指针的分类
1. 字符指针
//定义了一个字符指针的变量,只能存放字符型数据的地址编号
char *p;
char ch;
p=&ch;
2. 短整型指针
//定义了一个短整型指针的变量,只能存放短整型数据的地址编号
short int *p;
short int a;
p=&a;
3. 整型指针
//定义了一个整型指针的变量,只能存放整型数据的地址编号
int *p;
int a;
p=&a;
/*
注:多字节变量,占多个存储单元,每个存储单元都有地址编号,C语言规定,存储单元编号最小的那个编号,是多字节变量的地址编号
*/
4. 长整型指针
//定义了一个长整型指针的变量,只能存放长整型数据的地址编号
long int *p;
long int a;
p=&a;
5. float型的指针
//定义了一个float型的指针型变量p,只能存放float型变量的地址
float *p;
float a;
p=&a;
6. duoble型的指针
//定义了一个duoble型的指针型变量p,只能存放duoble型变量的地址
duoble *p;
duoble a;
p=&a;
7. 函数指针
8. 结构体指针
9. 指针的指针
10. 数组指针
指针转换
#include <stdio.h>
int abc(int a,int b){
return 0;
}
int main()
{
int a,(*b)(int,int)=abc;
/*
int a
int (*b)(int,int)
变量a 整型 int
变量b 指针 指向函数 两个int类型的参数,一个int类型的返回值
abc 函数名 函数名-指针转换
值: 函数abc的地址
类型: 指针 指向函数 两个int类型的参数,一个int类型的返回值
变量b的值是什么?函数abc在内存种的地址
变量b的值是什么类型? int(*)(int,int)
*/
void(*c)(void)=(void(*)(void))b;//其实此处,可以省略(void(*)(void))强制转换,=运算符会自动隐式转换
/*
变量c 指针 指向函数
b 变量 左值转换 值:函数abc的地址、类型:int(*)(int,int)
变量c中的值是什么类型? void(*)(void)
*/
a=((int(*)(int,int))c)(1,2); //此处不能省略强制类型转换
//a=c(1,2);error: too many arguments to function 'c'|
printf("%d",a);//0
return 0;
}
指针比较
只有两个相同类型的指针指向同一个数组的元素的时候,比较大小才有意义,指向前面元素的指针小于指向后面元素的指针
int a[10];
int *p,*q;
p=&a[1];
q=&a[6];
//结论:p<q
指针减法
只有两个相同类型的指针指向同一个数组的元素的时候,做减法才有意义,做减法的结果是,两个指针指向的中间有多少个元素
int a[10];
int *p,*q;
p=&a[0];
q=&a[3];
printf("%d\n",q-p);//3
//q保存的相当于第4个元素的地址,所以才是3
1.jpg
指针数组
多级指针
int main()
{
int i,*pi=&i,**ppi=π
**ppi=1;//其实此处改变的是i的值
*ppi=1;//修改的是pi的值
int j;
pi=&j;
**ppi=3;//赋值给了变量j
return 0;
}