指针的引入
-
为函数修改实参提供支持。
-
为动态内存管理提供支持。
-
为动态数据结构提供支持。
-
为内存访问提供另一种途径。
指针概述
-
内存地址:系统为了内存管理的方便,将内存划分为一个个的内存单元(1个内存单元占1个字节),并为每一个内存单元进行了编号,内存单元的编号称为该内存单元的地址。一般情况下,我们每一个变量都是由多个内存单元构成的,所以每个变量的内存地址,其实就是这个变量对应的第一个内存单元的地址,也叫首地址。
-
变量指针:变量地址称为该变量的指针。变量地址往往是指变量在内存中第一个内存单元的编号(首地址)。
-
指针变量:存放其他变量地址的变量。
-
指向:指针变量中存放“谁”的地址,就说明该指针变量指向了“谁”。
-
* :指针运算符
案例:
/** * 指针 初识 */ #include <stdio.h> void main() { // 定义一个普通/一般变量 int i = 3; // 定义一个指针变量,并赋值 int *i_point = &i; // 指针变量的数据类型要和存储的地址变量类型一致 // 访问普通变量(直接访问) printf("直接访问-%d\n",i); // 3 // 访问指针(地址访问)%p访问地址 printf("地址访问-%p\n",i_point); // 访问指针变量(间接访问) printf("间接访问-%d\n",*i_point); // 3 }
指针变量的定义
语法:
数据类型 *变量列表;
举例:
int a; // 普通变量 int *a,*b; // 指针变量
注意:
-
虽然定义指针变量 *a ,是在变量名前加上 * ,但是实际变量名为 a ,而不是 *a ;
-
使用指针变量间接访问内存数据是,指针变量必须要有明确的指向;
-
如果想借助指针变量间接访问指针变量保存的内存地址上的数据,可以使用指针变量前加 * 来间接访问;
指针变量前加 * ,也称为对指针变量 解引用 。
int i = 5, *p; p = &i; // 将i的地址赋值给指针变量p printf("%d\n",*p);// 间接访问i的值,也称为解引用p对应地址空间的值
-
指针变量只能指向同类型的变量,借助指针变量访问内存,一次访问的内存大小是取决于指针变量的类型。
-
指针变量在定义同时可以初始化:这一点和普通变量是一样的。
int i = 5; int *p = &i; // 定义的同时初始化
指针变量的使用
使用
-
指针变量的赋值:
// 方式1 int a,*p; p = &a; // 指针变量的值是其他变量的地址 // 方式2 int a,*p,*q = &a; p = q;
-
操作指针变量的值
int a,*p,*q = &a; p = q; printf("%p",p); // 此时返回的是变量a的地址空间
-
操作指针变量指向的值
int a =6,*q = &a; printf("%d",*q); // 6
两个有关运算符的使用
-
& 取地址运算符。 &a是变量a的地址。
-
* 指针运算符 (或称“间接访问”运算符),*p是指针变量p指向的对象的值。
案例:
#include <stdio.h> void main() { int a,b; int *pointer_1, *pointer_2; a=100; b=10; pointer_1=&a; pointer_2=&b; printf("a=%d,b=%d\n",a,b); printf("pointer_1=%d,pointer_2=%d\n",*pointer_1,*pointer_2); }
案例1:
声明a,b两个一般变量,使用间接存取的方式实现数据的交换?
代码:
/** * 需求:声明a,b两个一般变量,使用间接存取的方式实现数据的交换? */ #include <stdio.h> void main() { // 声明5个变量 int a = 3,b = 5,*p_a=&a,*p_b=&b,*p_t; // 交换前输出 printf("%d,%d\n",*p_a,*p_b); // 交换位置 p_t = p_a; p_a = p_b; p_b = p_t; // 交换后输出 printf("%d,%d\n",*p_a,*p_b); }
案例2:
指针变量应用。输入a、b两个整数,按先大后小的顺序输出a和b。
代码:
/* 需求:指针变量应用。输入a、b两个整数,按先大后小的顺序输出a和b。 */ #include <stdio.h> void main() { int a = 3,b = 5,*p_a = &a,*p_b = &b,*p_t; if( a < b) { p_t = p_a;// 操作指针变量,不会影响到数据本身 p_a = p_b; p_b = p_t; } printf("按从大到小输出a,b的值:%d > %d\n",*p_a,*p_b); }
代码:不推荐
/* 需求:指针变量应用。输入a、b两个整数,按先大后小的顺序输出a和b。 */ #include <stdio.h> void main() { int a = 3,b = 5,*p_a = &a,*p_b = &b,*p_t; if( a < b) { *p_t = *p_a;// 操作指针地址指向的内存空间,也就是直接操作变量a *p_a = *p_b; *p_b = *p_t; } printf("按从大到小输出a,b的值:%d > %d\n",*p_a,*p_b); }
指针变量做函数参数
指针变量做函数参数往往传递的是变量的地址(首地址),借助于指针变量间接访问是可以修改实参
变量数据的。
案例1:
需求:要求用函数处理,用指针变量作函数的参数
-
方式1:交换指向(指向的普通变量的值不变)
#include <stdio.h> /* 需求:指针变量应用。输入a、b两个整数,按先大后小的顺序输出a和b。 */ /* 自定义函数,实现两个数的比较 */ void swap(int *p_a,int *p_b) { int *p_t; // 这种写法,只会改变指向,不会改变地址对应空间的数据 p_t = p_a; p_a = p_b; p_b = p_t; printf("%d > %d\n",*p_a,*p_b); // 5 > 3 } void main() { int a = 3,b = 5; if(a < b) swap(&a,&b); // int *p_a = &a,int *p_b = &b printf("%d > %d\n",a,b);// 3 > 5 }
方式2:交换值(指向的普通变量的值改变)
#include <stdio.h> /* 需求:指针变量应用。输入a、b两个整数,按先大后小的顺序输出a和b。 */ /* 自定义函数,实现两个数的比较 */ void swap(int *p_a,int *p_b) { int t; // 这种写法,只会改变指向,不会改变地址对应空间的数据 t = *p_a; *p_a = *p_b; *p_b = t; printf("%d > %d\n",*p_a,*p_b); // 5 > 3 } void main() { int a = 3,b = 5; if(a < b) swap(&a,&b); // int *p_a = &a,int *p_b = &b printf("%d > %d\n",a,b);// 5 > 3 }