指针
1. 概念:
计算机中所有的数据都必须放在内存中,不同数据类型的数据占用不一样的字节数。为了正确的访问这些数据,必须为每个字节都编上号码,我们把这些成为地址或指针。
在C语言中将地址形象的成为指针,一个变量的地址成为变量的‘指针’。一个专门用来存放另一个变量的的地址的变量,则称他为“指针变量”。
地址:操作系统的寻址空间编号,也就是操作系统给每个存储单元分配了统一的编号
指针就是地址
指针变量就是保存地址编号的变量
在32bit平台下,地址总线32位,所以地址编号32位,指针变量也是32位即4字节。
32bit系统范围0x0000 0000~0xFFFF FFFF
2.指针的定义方法
格式:
数据类型 *指针变量;
数据类型 *指针变量1,*指针变量2,*指针变量3,........;
*号在指针变量定义时不能省略,否则就会变成一般变量的定义。
指针运算符
&:获取一个变量的地址
*:再定义一个指针变量时,起到标识作用,标识定义的是一个指针变量
除此之外其他地方都表示获取一个指针变量保存的地址里面的内容。
扩展:如果一行中定义多个指针变量,每个指针变量的前面都需要加*修饰
注意:
1.无论什么类型地址,都是存储单元的编号,在32bit下都是4字节,即任何类型的指针变量都是4字节
2.对应的类型的指针变量,只能存在对应的变量地址
如:整型指针变量,只能存放整型变量的地址
扩展:char ch;ch占一个字节,他有一个地址编号0x1900,这个地址编号就是ch的地址
整型变量int a;a占4字节,它占4字节的存储单元,对应占4个地址编号0x2000~0x2003,我们一般只研究首地址即0x2000
#include<stdio.h>
int main()
{
// int a=10;
int *p;
// p = &a;
// printf("%d\n",a);//打印变量a的值
// printf("%p\n",&a);//打印a的地址
// printf("%d\n",*&a);//对a的地址取值再去地址,还是它本身
// printf("%p\n",p);//指针变量p也是a的地址
// printf("%p\n",*&p);//取地址的地址再取值,还是它本身
// printf("%d\n",*p);//取地址里面的值
// printf("%p\n",&*p);//取地址的值,再取这个值的地址
char *pch;
short *pt;
float *pf;
double *pdou;
long *pl;
long long *pll;
printf("%d\n",sizeof(p));
printf("%d\n",sizeof(pch));
printf("%d\n",sizeof(pt));
printf("%d\n",sizeof(pf));
printf("%d\n",sizeof(pdou));
printf("%d\n",sizeof(pl));
printf("%d\n",sizeof(pll));
return 0;
}
3.指针的引用
指针变量只能存放地址,与指针相关的两个运算符是&和(取地址运算)*(取值,指针运算符)
4.指针的分类
按照数据类型进行分类:
1.字符指针:
字符型数据地址
2.短整型指针:
3.整形指针
4.长整型指针
5.float型指针
6.double型指针
函数指针:本质是一个指针,指向一个函数的指针
指针函数:本质是一个函数,函数的返回值是一个指针
结构体指针:本质是指针,指向一个结构体的指针
指针的指针:指向指针的指针,二级指针
数组指针:本质是一个指针,表示指向一个数组的指针
指针数组:本质是一个数组,数组中的每个元素都是一个指针
无论什么类型的变量,在32位系统下都是4字节,只能存放对应类型的变量的地址编号
5.指针和变量的关系
指针可以存放变量的地址编号
在程序中,引用变量的方法
1.直接通过变量名称;
2.通过指针变量来引用变量
字节序:
字节序又称为端序或尾序,在计算机领域中,指电脑内存中或数字电路通信中,占用多个字节的字节排列顺序。
有两种规则:
大端序:低位字节 存放高位地址,高位字节存放低位地址
小端序:将低位放在低位地址,高位放在高位地址
//小端序
int main()
{
int a = 0x12345678;
int b = 0x78563412;
char *p1,*p2;
p1 = (char*)&a;
p2 = (char*)&b;
printf("%p %p\n",p1,p2);
printf("%x %x\n",*p1,*p2);
p1++;
p2++;
printf("%p %p\n",p1,p2);
printf("%x %x\n",*p1,*p2);
p1++;
p2++;
printf("%p %p\n",p1,p2);
printf("%x %x\n",*p1,*p2);
p1++;
p2++;
printf("%p %p\n",p1,p2);
printf("%x %x\n",*p1,*p2);
//000000000062FE0C 000000000062FE08
//78 12
//000000000062FE0D 000000000062FE09
//56 34
//000000000062FE0E 000000000062FE0A
//34 56
//000000000062FE0F 000000000062FE0B
//12 78
return 0;
}
注:
*p取几个字节由指针类型决定
如果是字符型指针类型,就取一个字节
整型就取4个字节
p++指向下个对应的数据类型的数据
如果是字符型指针++,指针存放地址编号+1
如果只整型指针++,指针存放编号+4
注:
(*p)++和*p++的区别:
1.(*p)++表示对p指针所指向的值取++运算,等价于a++
2.*p++表示对p指针指向的地址取++运算,然后再取值,*p++和(*p)++等价,运算优先级相同,从左到右依次进行运算。
6.指针与数组元素之间的关系
变量存放在内存中,有地址编号,数组十多个同类型的变量的集合。
每个变量都占用空间,都有地址编号
指针变量当然可以存放数组元素地址
数组元素引用方法:
1.数组名【下标】
2.指针名【下标】
C语言规定数组名就是数组的首地址,即第0个元素的地址编号是个常量
注:p和a不同,p是指针变量,ashi常量,所以可以给p赋值,但不能给a赋值
7.指针运算
1.指针可以加一个整数,往下指几个它指向的变量,结果还是地址编号
前提:指针指向数组的时候,加一个整数才有意义
2.两个相同类型的指针可以比大小
前提:指向同一个数组元素时,比较大小才有意义
指向前面的元素的指针,小于只想后面元素的指针
3.两个相同类型的指针可以做减法
前提:必须是相同类型的指针指向同一个数组元素的时候,做减法才有意义
结果是:两个指针指向的中间有多少元素
4.两个相同类型的指针可以互相赋值
注意:只有相同类型才能赋值(void*类型除外)
8.指针数组-数组指针
1.指针数组的概念:
本质是数组,数组中的每个元素都是一个指针变量
2.指针数组定义方法
类型说明符 * 数组名【元素个数】
3.指针数组的分类
字符指针数组char*p【10】,短整型、整型、长整型、float型、double型、结构体、函数
4.数组指针
定义:本质是指针,指针指向数组的首地址
定义方法:
类型说明符 (*指针变量名)【数组内元素个数】
说明:
1.arr指向了数组中的第0行地址
2.arr指向了数组中的第0行第0列元素的地址
3.arr+或&arr【i】指向了第i行的地址,它的类型是4个整数的数组指针
4.(arr+i)或&arr【i】【0】表示数组中第i行第0列元素地址,他的类型是int型指针
9.指针变量做函数形参
10.指针函数-指针做为函数的返回值
指针函数本质是一个函数,不过函数的返回值是一个指针
格式:
类型 *函数名 (形参列表)
11.函数指针-指针保存函数的地址
本质是指针,指针指向一个函数
咱们定义的函数,在运行程序时,会将函数的指令加载到内存的代码段,所有函数也有起始地址
C语言规定:函数的名字就是函数的首地址,即函数的入口地址,定义一个指针变量来存放函数的地址,这个指针变量就是函数的指针变量。
定义:
返回值类型 (*函数指针变量名)(形参列表)
函数指针的返回值、参数个数和参数类型要和原函数保持一致