07_指针变量

综合案例:在这里插入图片描述

#include<stdio.h>

void test01()

{

	int num = 0x01020304;

	char *p;

	short *p2;

	

	p = #

	p2=#


	printf("%#x\n", *(short *)(p+1));//0x203

	printf("%#x\n", *(short *)((char *)p+1));//0x203


	return;

}

int main(int argc,char *argv[])

{

	test01();

	return 0;

}

知识点1【指针变量的初始化】

void test02()

{

	int num = 10;

	int data = 200;


	//如果 局部 指针变量 不初始化 保存的是随机的地址编号(千万别取值) 

	int *p;


	//不想让指针变量指向任何地方 应该初始化为NULL(千万别取值)

	//#define NULL    ((void *)0)

	int *p1 = NULL;



	//将指针变量初始化为合法的地址(可以取值)

	//千万别看成 *p2 = & num;

	//*修饰p2为指针变量,p2=& num;

	int *p2 = #//第一步:int *p2;   第二步:p2=& num;

	printf("%d\n", *p2);//num==10


	

	//指针变量 p2本质 是一个变量 可以更改指向

	p2 = &data;

	printf("%d\n", *p2);//data==200


}

运行结果:在这里插入图片描述总结:指针变量的初始化
1、指针变量初始化为NULL

int p = NULL;//不要对p进行p操作 容易出段错误

2、指针变量初始化为 合法的空间

int num = 10;

int *p = #//第一步定义指针变量int *p; 第二步给指针变量赋值:p=&num在这里插入图片描述知识点2【&取地址符 和 *指针解引用符 区别】(使用中…)

void test03()

{

	int num = 10;

	int *p;


	//num的类型是 int 类型

	//&num的类型是 int * 类型

	//如果对一个变量取地址 整个表达式的类型 就是变量的类型+*.


	p=#


	//p的类型是 int *类型

	//*p的类型是 int 类型

	//如果对指针变量取* 整个表达式的类型是 指针变量的类型-*.


	//高级总结:如果&和*同时存在 可以相互抵消(从右-->左)。(重要)


	//论证:*p ==num

	//*p=*&num==num;


	//&*&*&num == &num

	printf("p=%p\n",p);

	printf("&*&**&p=%p\n",&*&**&p);

}

int main(int argc,char *argv[])

{

	test03();

	return 0;

}

运行结果:在这里插入图片描述知识点3【指针的注意事项】(重要)
1、void 不能定义变量

void num;//错误的 系统不知道 num的大小

2、void *可以定义变量

void *p;//p的类型为void *, 而void *指针类型,32为平台4字节,系统知道给p开辟4字节

//p叫万能指针 p可以保存 任意一级指针

char ch;

p = &ch;//char *

int num;

p = #//int *

float f;

p = &f;//flaot *

对于p 不能直接使用*p操作。 必须实现对p进行强制类型转换

void test04()

{

int num = 10;

void *p;

p = #

//printf("*p = %d\n", *p);//err 因为p的指向类型为void  系统确定不了宽度

printf("*p = %d\n", *(int *)p);//ok p临时的指向类型为int 系统确定宽度4B

}

3、不要对 没有初始化的 指针变量 取*

int *p;

printf("*p=%d\n",*p);

//因为p没有初始化 内容随机 也就是p指向了一个未知空间 系统不允许用户 取值*p操作

4、不要对 初始化为NULL的指针变量 取*

//NULL 就是(void *)0 地址,也是内存的起始地址 受系统保护

int *p=NULL;

printf("*p = %d\n", *p);//也不能 *p

5、不要给 指针变量 赋普通的数值。

int *p = 1000;//此时的1000对于p来说 是地址编号 1000

//p表示在地址编号为1000的位置 取值 ,而地址编号1000不是合法的空间 所以不能p

printf("*p = %d\n", *p);//也不能 *p

6、指针变量不要操作越界的空间。

char num=10;

int *p = #

//num只占1B空间 而p的指向类型为int 所以*p取值宽度为4B,所以越界3B

printf("*p =%d\n",*p);//操作非法空间

知识点4【数组元素的指针】在这里插入图片描述案例:通过数组元素的指针变量 遍历 数组的元素

void test05()

{

	int arr[5]={10,20,30,40,50};

	int n = sizeof(arr)/sizeof(arr[0]);

	int i=0;


	//p保存了 第0个元素的地址(首元素的地址)

	int *p = &arr[0];

	printf("*p = %d\n", *p);//10


	p++;//p=p+1

	printf("*p = %d\n", *p);//20


    //前提是p保存的是第0个元素的地址

	p=&arr[0];

	for(i=0;i<n;i++)

	{

		//printf("%d ", arr[i]);

		//p+i代表的是第i个元素的地址

		//*(p+i)代表的是第i个元素的值

		printf("%d ", *(p+i) );

	}

	printf("\n");

}

运行结果:在这里插入图片描述案例提高:

void test06()

{

	int arr[5]={10,20,30,40,50};

	int *p = &arr[1];

	p++;

	p++;

	printf("%d\n", *(p+1));//50

}

运行结果:50
案例:通过数组元素的指针变量给数组的元素 获取键盘输入

void test07()

{

	int arr[5]={0};

	int n = sizeof(arr)/sizeof(arr[0]);

	int i=0;

	int *p = &arr[0];


	printf("请输入%d个int数据\n",n);

	for(i=0;i<n;i++)

	{

		//scanf("%d", &arr[i]);

		scanf("%d", p+i);//p+i == &arr[i]

	}

	

	for(i=0;i<n;i++)

	{

		printf("%d ",*(p+i));

	}

	printf("\n");


}

运行结果:在这里插入图片描述知识点5【数组的[]和*()的关系】(重要)

void test08()

{	

	//数组名arr 作为类型 代表的是数组的总大小 sizeof(arr)

	//数组名arr 作为地址 代表的是首元素地址(第0个元素的地址)

	int arr[5]={10,20,30,40,50};

	int n = sizeof(arr)/sizeof(arr[0]);

	int *p = NULL;


	//p = &arr[0];//arr == &arr[0]

	p = arr;


	//在使用中 本质:[] 是*( ) 缩写

	//缩写规则:+左边的值 放在[]左边边  +右边的值 放在[]里面

	printf("arr[1]=%d\n",arr[1]);//20

	printf("arr[1]=%d\n",*(arr+1));//20

	printf("-------------------------\n");

	printf("arr[1]=%d\n",*(1+arr));//20 

	printf("arr[1]=%d\n",1[arr] );//20


	//为啥 arr代表的是  第0个元素的地址(&arr[0])

	//&arr[0] == &*(arr+0) == arr+0 == arr

	//所以:数组名arr代表第0个元素的地址

}

总结:
1、【】是*()的缩写
2、数组名arr 代表的是数组 首元素地址(第0个元素的地址)
知识点6【arr 和 &arr的区别】(了解)

arr:数组的首元素地址。
&arr:数组的首地址。在这里插入图片描述

void test09()

{

	int arr[5]={10,20,30,40,50};

	printf("arr = %u\n",arr);

	printf("arr+1 = %u\n",arr+1);

	printf("-------------\n");

	printf("&arr = %u\n",&arr);

	printf("&arr+1 = %u\n",&arr+1);

}

运行结果:在这里插入图片描述数组名arr 是一个符号常量。不能被赋值。(了解)

void test10()

{

	int arr[5]={10,20,30,40,50};

	//arr=1000;//err arr符号常量 不能被赋值

 

	//arr++;//arr=arr+1; err

	arr+1;//ok

}

知识点7【指向同一数组的两个元素的指针变量 间关系】

void test11()

{

	int arr[5]={10,20,30,40,50};

	int *p1 = arr;

	int *p2 = arr+3;

	//1、指向同一数组的两个指针变量相减 返回的是相差元素的个数

	printf("%d\n",p2-p1);//3


	//2、指向同一数组的两个指针变量 可以比较大小 > < >= <= == !=

	if(p2>p1)

	{

		printf(">\n");

	}

	else

	{

		printf("<=\n");

	}

	//3、指向同一数组的两个指针变量 可以赋值

	p1=p2;//p1 和 p2指向同一处


	//4、指向同一数组的两个指针变量 尽量不要相加

	printf("p2=%u\n",p2);

	//p1+p2;//err 越界很厉害了


	//5、[]里面在不越界的情况下 可以为负数

	printf("%d\n",p2[-2]);//20

}

案例:

void test12()

{

	int arr[5]={10,20,30,40,50};

	int *p = arr;


	printf("%d\n", *p++);//10

	printf("%d\n", (*p)++);//20

	printf("%d\n", *(p++));//21

}
发布了20 篇原创文章 · 获赞 0 · 访问量 26

猜你喜欢

转载自blog.csdn.net/weixin_45992045/article/details/104675898
今日推荐