6.【指针】

【指针】【重点】
	指针的重要性
		表示一些复杂的数据结构
		快速的传递数据
		使函数返回一个以上的值
		能直接访问硬件
		能够方便的处理字符串
		是理解面向对象语言中引用的基础

		总结:指针是C语言的灵魂

	指针的定义
		地址
			内存单元编号
			从0开始的非负整数
			范围:4G 【0----(4G-1)】
		指针
			指针就是地址,地址就是指针
			地址就是内存单元的编号
			指针变量是存放地址的变量
			指针和指针变量是两个不同的概念
			但是要注意:通常我们叙述时会把指针变量简称为指针,实际它们含义并不一样
			指针的本质就是一个操作受限的非负整数
	指针的分类
		1.基本类型指针【重点】
			--------------------------------------
			For example 1:
			#include <stdio.h>
			int main(void)
			{
				int * P;  //p是变量的名字,int * 表示p变量存放的是int类型变量的地址,即int * 只能存放整型变量的地址
				int i = 3;
				p = &i; //OK,&是取地址符
			/*	p = i    error, 因为类型不一致,p只能存放int类型的变量的地址,不能存放int类型变量的值 */
			/*	p = 55;	error,原因同上 */
				return 0;
			}
			----------------------------------------------------------------
			For example 2:
			#include <stdio.h>
			int main(void)
			{
				int * P;  /*
							p是变量的名字,int * 表示p变量存放的是int类型变量的地址,即int * 只能存放整型变量的地址
							int * p;不表示定义了一个名字叫做*p的变量,而应该是p是变量名,p变量的数据类型是int *整型变量指针
							相当于这也是一个声明,声明了 int * 是它的数据类型,而后面的p才是它的变量名字
							所谓int *;类型--->实际就是存放int变量地址的类型
							int *限制了 后面的p只能存放整型变量的地址

						  */
				int i = 3;
				int j;
				p = &i;   /*
							1.p保存了i的地址,因此说p指向i
							2.p不是i,i也不是P,更准确的说:修改p的值不影响i的值,修改i的值也不影响p的值
							3.如果一个指针变量指向了某个普通变量,则:
								*指针变量  就完全等同于  普通变量
							例子:
								如果p是个指针变量,并且p存放了普通变量i的地址
								则p指向了普通变量i
								*p 就完全等同于 i
								或者说:在所有出现*p的地方都可以替换成i
										在所有出现i的地方都可以替换成*p 

								*p 就是以p的内容为地址的 变量
						  */
						 		 
				j = *p; //等价于 j=i;
				printf("i=%d,j=%d\n",i,j);
				return 0;
			}
			-------------输出结果为i=3,j=3----------------------------

			---------------指针常见错误解析----------
			For example 1:
			#include <stdio.h>
			int main(void)
			{
				int * p;
				int i=5;

				*P = i;   /*error,解析:
									因为p开始的时候并没有经过初始化,所以p里面肯定是一个垃圾值,而*P就代表这个垃圾值的地址
									且并不知道这个垃圾值是多少,而因为将i赋值给*P,就相当于强行将*p里面垃圾值的地址给
									替换成了i的地址。试想,如果有一个软件正在计算机内运行,且占用的内存恰好就为这个垃圾值的地址
									那么一旦这样进行替换,这个运行的软件就会崩溃。
						  */
				printf("%d\n",*P);

				return 0;
			}
			-------这样写的话,整个程序就会出错而也没有输出结果----------
			For example 2:
			#include <stdio.h>
			int main(void)
			{
				int i= 5;
				int * p;
				int * q;

				p = &i;
			/*	*q = p;   error, *q 和 p的类型不一致,程序会报错  因为*q代表一个变量,而p只代表一个地址 */
			/*	*q = *p;  error,  *q 是未知的地址 不能更改未知的地址,相当于上面的例题 */
			/*	p = q;    error, q是垃圾值,q赋给P, p也变成了垃圾值  */
				printf("%d\n",*q);    
									/*  q的空间是属于本程序的,所以本程序可以读写q的内容,但是如果q内部是垃圾值,
										则本程序不能读写*q的内容,因为*q所代表的内存单元的控制权限并没有分配给本程序。
										所以本程序运行到 printf行时就会立即出错。    
									*/
				return 0;
			}
			------------------------------------------------------------------------
			经典指针程序_两个数字互换举例:
			#include <stdio.h>
			int main(void)
			{
				int a = 3;
				int b = 5;
				int t;
				t = a;
				a = b;
				b = t;
				printf("a=%d,b=%d\n",a,b);
				return 0;
			}
			-------输出的结果为a=5,b=3 互换成功-----------------------------
			#include <stdio.h>
			void huhuan_1(int a, int b)
			{
				int t;

				t = a;
				a = b;
				b = t;            //没有返回值
				return;
			}
			int main(void)
			{
				int a = 3;
				int b = 5;
				huhuan_1(a,b);  //这里最终互换的是上面形参里面的a和b,而和实际的主函数里面的a和b的值没有关系
								//所以最终互换失败,a依然是3,b也依然是5
				printf("a=%d,b=%d\n",a,b);
				return 0;
			}
			--------输出的结果还是a=3,b=5互换失败-------------------------------
			#include <stdio.h>
			void huhuan_2(int * p, int * q)
			{
				int * t;  //如果要互换p和q的值,则t必须是 int * 不能是 int 否则会出错

				t = p;
				p = q;
				q = t;
				return;
				        /*最终更换的是a和b的地址编号,但实际的值并没有改变 
				          形参的改变不会影响实参*/
			}
			int main(void)
			{
				int a = 3;
				int b = 5;
				huhuan_2(&a,&b);     //huhuan(*p,*q); 是错误的,huhuan(a,b); 也是错误的
				printf("a=%d,b=%d\n",a,b);
				return 0;
			}
			------------输出的结果还是a=3,b=5依然互换失败--------------------------------
			#include <stdio.h>
			void huhuan_3(int * p, int * q)
			{
				int t;    //如果要互换*p和*q的值,则t必须定义成int不能定义成int*因为*p代表的是一个以p的内容为地址的变量

				t = *p;  //p是int *那么*p是int 是最终变量的值
				*p = *q;
				*q = t;
				return;
				        
			}
			int main(void)
			{
				int a = 3;
				int b = 5;
				huhuan_3(&a,&b);     
				printf("a=%d,b=%d\n",a,b);
				return 0;
			}
			---------------------输出结果是a=5,b=3互换成功------------------------------------
			如何通过被调函数修改主调函数的的值:
				1.实参是普通变量的地址
				2.形参必须为指针变量
				3.在被调函数中通过
						*形参名 = ......
						的方式就可以修改主调函数相关变量的值

			-------------------------------------------------------------------------
						* 号的三种含义:
							1.乘法
							2.定义指针变量
								int * p; //定义了一个名字叫p的变量,int *表示p只能存放int类型变量的地址
							3.指针运算符
								该运算符放在已经定义好的指针变量的前面
								如果p是一个已经定义好的指针变量
								则 *p表示 以p的内容为地址的变量
			------------------------------------------------------------------------------------------------
			one:
			#include <stdio.h>
			int main(void)
			{
				int * p;   //等价于int *p; 也等价于int* p;
				int i = 5;
				char ch = 'A';    //如果要表示单个字符,c语言要求用单引号括起来,如果要表示字符串,用双引号括起来
				p = &i;   //*p 以p的内容为地址的变量
				*p = 99;
				printf("i=%d,*p=%d\n",i,*p);
				//p = ch;  //error
				//p = 5;   //error
				//p = &ch; //error
				return 0;
			}
			----输出结果为i=99,*P=99(因为p=&i,所以当把99赋值给*P的时候,相当于也把99赋值给了i,因为i的地址是不变的)---------
			--------------------------------------
			two:检测实参和形参是否是同一个变量
			--------------------------------------
			#include <stdio.h>
			void f(int x)
			{
				x = 99;     //局部变量只能在定义的函数内使用
			}
			int main(void)
			{
				int i = 6;    //局部变量
				printf("i = &d\n",i);
				f(i)                   //实参和形参一定不是一个变量,跟实参和形参的名字没有关系,不会因为都是i就是一个变量
				printf("i = %d\n",i)
				return 0;
			}
			----输出的结果为i = 6, i = 6(证明f(i)的括号里面的i跟上面的x = 99;没有任何关系)-----------
			-------------------------------------------------------------------------------------------------
			#include <stdio.h>
			void swap(int i, int j)
			{
				int t;
				t = i; i = j; j = t;
			}
			int main(void)
			{
				int a = 3;
				int b = 5;

				swap(a,b);   //调用swap函数
				printf("a = %d,b = %d\n", a, b);

				return 0;
			}
			同样的即便是使用带返回值的函数,也是一样的结果,a=3,b=5
			--------------------------------------------------------
			#include <stdio.h>
			int swap(int i,int j)
			{
			        int t;
			        t = i;
			        i = j;
			        j = t;
			        return 0;
			}
			int main()
			{
			        int a = 3;
			        int b = 5;
			        swap(a,b);
			        printf("a = %d,b = %d \n",a,b);
			        return 0;
			}
			-----------------------------------------------
			借助指针的地址换换来实现值的互换:
			---------------------------------
			#include <stdio.h>
			void swap(int *i,int *j)
			{
			        int t;
			        t = *i;
			        *i = *j;
			        *j = t;
			}
			int main()
			{
			        int a = 3;
			        int b = 5;
			        swap(&a,&b);
			        printf("a = %d,b = %d \n",a,b);\
			        return 0;
			}
			--------------------这样结果就会成功互换a=5,b=3---------------------------
			调用函数的执行过程:
				1.当程序在执行调用swap函数的时候,会立马给形参i和j分配内存空间以便用来存储由实参传递过来的a和b的值
				2.在swap(int i, int j)接收到实参传递的过来的值以后,将3传递给i,将5传递给j,然后执行{}内的调换运算,
				  当执行完成之后,i和j的值已经互换了,即i=5和j=3,这时候会立刻释放之前分配给形参i和j的内存空间,然后
				  程序会继续向下执行到printf("a = %d,b = %d\n", a, b);
				3.这个时候因为printf输出的是a和b的值,可是因为a和b的值并没有因为调用swap函数而发生变化,所以依然维持原值输出。
				  即i = 3, b =5
				4.swap函数的内部只是执行了形参内的变量对调,并没有影响到实参。
				5.所以要实现上例总的值互换就需要借助指针的地址互换来实现。
			------------------------------------------------------------------------




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值