目录
b.原因二: 取值运算符会根据指针变量的类型,访问不同大小空间(类似于印章的大小)
一、指针的认识
说到指针不得不提起变量。
变量的四要素 变量类型、变量名、变量值和变量的地址 。
可以用一句话来形容指针,地址就是指针,指针就是地址。指针 == 地址。
定义一个变量int a = 10,如何访问变量的里的值?有两种方式,第一种通过变量的名字a来访问变量的值,称为“直接访问”。第二种通过变量的*(&a)地址来访问变量的值,称为“间接访问”。&取变量地址的运算符,* 将地址内的值取出来。*(&a)的意思是从a的地址,把a的值读取出来。
比如:小明刚考上一所大学,开学前准备去学校新生报道,你需要提前知道学校的位置在哪?有两种方式可以知道学校位置,第一种方式 xxxxx大学,通过学校的名字知道学校的位置(学校名字 == 变量名)。第二种方式通过地址找到学校位置,广东省广州市xxx区花山镇育才路001号 (地址 == 指针)。
代码演示:
#include<stdio.h>
int main()
{
int a = 10;
printf("a的值是%d\n",a); //用变量名字访问a
printf("a的地址是%p\n",&a); //a 的地址用16进制表示
printf("用变量a的地址,访问变量a的值%d\n",*(&a)); //用变量a的地址访问a的值
//&取地址运算符,&a 取出变量a的地址
return 0; //* 将地址内的值读出运算符,取值运算符
} //*(&a) 从a的地址中&a ,用*取出&a地址的值
二,指针变量
1.什么是指针变量?
什么是整形变量?就是存放整形数的变量。
什么是字符变量?就是存放字符的变量。
什么是指针变量?指针变量就是存放指针的变量。
什么是指针变量?指针变量就是存放地址的变量。
指针变量一般简称指针
如何定义一个指针变量?如何通过指针变量来访问变量的内容?
int *p = &a;这里的*是标识符,告诉系统我是一个指针变量,是用来保存变量a地址的。
代码演示:
#include<stdio.h>
int main()
{
int a = 10;
int *p; //指针变量的定义,这里的*是标识符,告诉系统我是一个指针变量,是用来保存地址的和下方
的运算符不一样
p = &a; //指针变量的赋值,存放a的地址。 也可以称为指针变量指向a的地址
printf("a的值是%d\n",a);
printf("a的地址是%p\n",&a);
printf("用a的地址访问a的值%d\n",*(&a));
printf("指针变量p存放a的地址,用指针p变量访问a的值%d\n",*p);
//通过指针变量来访问变量的内容*p
//*p,*是取值运算符,p存放a的地址。*p是从a地址中把a的值“取出来”
return 0;
}
2.为什么指针变量要区分类型?
a.原因一: 指针类型不同增量也不同
原因一,代码演示:
#include<stdio.h>
int main()
{
int a = 0x1234;
int *p;
char *x;
p = &a;
x = &a;
printf("用int p指针变量访问 a的地址是%p\n",p);
printf("用char x指针变量访问 a的地址是%p\n",x);
putchar('\n');
printf("指针++p 是%p \n",++p); //指针变量的不同跨越的大小也是不一样
printf("指针++x 是%p \n",++x); //int指针变量跨越四个字节,char指针变量刮越一个字节,地址可以看出
return 0;
}
运行结果:
a.exe //编译运行
用int p指针变量访问 a的地址是000000000061FE0C
用char x指针变量访问 a的地址是000000000061FE0C
指针++p 是000000000061FE10
指针++x 是000000000061FE0D
详细解释:
int *p打印出来a的地址是 000000000061FE0C,++p后的地址是000000000061FE10。 因为指针类型为int整数型 所以++p 增量为4个字节 ,FE0C 增加了四个字节,变成FE10。 (指针p打印a的地址后四位是FE0C,C代表数为12字节,int整形指针++p增量为4个字 节,12字节+4字节=16,因为16进制进了1位,所以++p变成FE10 )
char *x打印出来a的地址000000000061FE0C(与int *p相同),++x后地址是000000000061FE0D因为指针类型是char,所以++x增量为1个字节,FE0C增加1个字节,变成FE0D。 (指针x打印a的地址后四位是FE0C,C代表数为12字节,char指针增量为1个字节,12+1=13, C 增一位字节变成D,所以++x 为FE0D)
b.原因二: 取值运算符会根据指针变量的类型,访问不同大小空间(类似于印章的大小)
原因二,代码演示:
#include<stdio.h>
int main()
{
int a = 0x1234;
int *p;
char *x;
p = &a;
x = &a;
putchar('\n');
printf("用int p指针变量访问 a的16进制值是%x\n",*p); //取值运算符*会根据指针变量的类型的不同,去访问不同空间大小
printf("用char x指针变量访问 a的16进制的值是%x\n",*x);//int 指针变量四个字节大小 char指针变量一个字节大小
return 0;
}
运行结果:
用int p指针变量访问 a的16进制值是1234
用char x指针变量访问 a的16进制的值是34 //指针变量类型不同,访问空间大小也不同
//类似于印章的大小,
3.指针变量有那些应用场景?
a、指针应用场景一:
只有函数调用的时候,程序才会给函数分配临时独立的内存空间,当函数调用完毕时给函数分配的内存空间会主动释放。函数与主函数main的内存空间并不相同,函数无法修改或直接访问主函数main内存空间的变量和值,函数需要通过指针的方式,间接访问主函数main的值。 所以想要在函数中访问并修改main主函数的值,需要在主函数main中给函数传递地址。
例如:封装一个函数,实现两个数的交换
#include<stdio.h>
void chagedata(int *pdata,int *pdata2)
{
int tmp;
tmp = *pdata;
*pdata = *pdata2;
*pdata2 = tmp;
}
int main()
{
int data = 10;
int data2 = 20;
printf("交换前data = %d ,data2 = %d\n",data,data2);
chagedata(&data,&data2); //在main函数中传递地址给chagedata函数,通过指针的方式在chagedata函数中间接访问并修改主函数main的值
printf("交换后data = %d ,data2 = %d",data,data2);
return 0;
}
运行结果:
交换前data = 10 ,data2 = 20
交换后data = 20 ,data2 = 10
b、指针应用场景二:
让指针指向固定内存地址区域(单片机、ARMbootloader)
#include<stdio.h>
int main()
{
int data = 10;
volatile unsigned int *p = (volatile unsigned int *)0x000000000061FE1C;
//让指针指向一个固定的内存地址
printf("data的地址是%p\n",&data);
printf("*p指向的地址是%p",p);
return 0;
}
运行结果:
data的地址是000000000061FE14
*p指向的地址是000000000061FE1C
4.指针变量与数组
a、如何定义一个指针变量指向数组
1.数组名字等于数组首地址 2.数组第一个元素地址等于数组首地址
代码演示:
#include<stdio.h>
int main()
{
int a[3] = {1,2,3};
int *p;
p = a; //数组名 等于 数组首地址
p = &a[0]; //数组第一个元素地址 等于 数组首地址
return 0;
}
b、如何通过指针遍历访问数组的值
代码演示:
#include<stdio.h>
int main()
{
int i;
int a[3] = {1,2,3};
int *p;
p = a;
for(i = 0;i<3;i++){ 第二种方式,指针访问数组,指针变量p可以用数组的下标法来访问值
printf(" %d ",p[i]);
}
putchar('\n');
p = a;
for( i = 0;i<3;i++){
printf(" %d ",*(p+i) ); //第二种方式,指针访问数组
}
putchar('\n');
p = a;
for(i = 0;i<3;i++){
printf(" %d ",*p++); //第三种方式,指针访问数组
}
return 0;
}
运行结果:
1 2 3 //第一种方式访问
1 2 3 //第二种方式访问
1 2 3 //第三种方式访问