1.用函数实现两变量值的交换
1).通过函数将两个数作为形参传入
//定义函数,实现两个变量值的交换:普通方式(不能交换)
void swap1(int x,int y){
int temp;
//进行交换
temp = x;
x = y;
y = temp;
}
当基本数据类型作为函数的参数时是值传递,并不能改变主调函数的值
2).传递地址方式(只交换地址)
//只交换两个变量的地址,也不能实现交换
void swap2(int *px,int *py){
int *ptemp;
ptemp = px;
px = py;
py = ptemp;
}
3).地址传递并交换连个地址中的值
//通过指针改变了两个值的内容,实现了交换
void swap3(int *px,int *py){
//px -->a py---->b
int ptemp;
ptemp = *px; // ptemp = 3;
*px = *py; // a = b; a = 5,b = 5
*py = ptemp; // b = 3; b = 3;
}
通过指针改变一个值的方式称为间接方式改变
2.指针常见的应用场景
1).通过指针间接的改变一个变量的值(详见第一个标题)
2).通过指针能够让函数有多个返回值
//实现计算器
void calculator(int x,int y,int *psum,int *pjian,int *pcheng,float *pchu){
//把x+y的结果放到主调函数中 sum变量中
*psum = x+y;
*pjian = x-y;
*pcheng = x*y;
*pchu = x/(float)y;
}
所谓的多个返回值并不是多个return,而是一次性的修改多个变量的值
3.二级指针
- 二级指针的使用
//定义一个变量
int a = 0;
//定义一个一级指针指向a,假设a的地址为0xf2
int *p = &a;
p == 0xf2;
*p == *0xf2 == a;
//定义一个二级指针指向p
int* *p1 = &p;
//此时p1的内存单元中存放的是p的地址,假设p的地址为0xf0
p1 == 0xf0;
*p1 == *0xf0这个地址所指向的内容 == 0xf2
**p1 == **0xf0 == *0xf2 == a;
二级指针就是一个指向指针的指针
3.指针为什么要区分类型
- 指针在内存中所占的字节数是由计算机地址总线的宽度所决定的,64位机中指针类型占8个自节,而指针之所以要区分类型,是为了在内存中计算变量时的准确.
//定义一个整型变量
int a = 245;
//定义一个整型的指针指向a
int *p = &a;
//取a的值
*p;
//如果定义一个char类型的指针指向a
char *p1 = &a;
//则在计算*p1时就不能够准确的算出a的值,因为只计算了1个字节
指针区分类型是为了准确的计算变量的值
4.数组指针的概念及定义
- 数组指针:指向数组元素的指针
//定义一个数组
int a[] = {1,2,3,4,5};
//定义一个指针指向数组a
int *ap = a;
//利用该指针遍历数组a
for (int i = 0; i < 5; i++){
printf("a[%d] = %d\n",i,*(ap+i));
}
- 使用指针或数组名都可间接的访问数组元素
//如果使用间接的方式访问数组的元素值
// 1) *(p+i) == a[i]
// 2) *(a+i) == a[i]
// p+i,a+i == &a[i]
1).指针pa进行+1或-1操作时不是内存地址的加减,而是指向下一个数组元素或上一个
2).同一个数组中的两个指针相减表示的是这两个指针之间差多少个元素
应用1:将一个数组逆序输出
void swap(char ch[],int length){
char *first = ch;
char *last = &ch[length-1];
char temp = 0;
while( last - first > 0 )
temp = *first;
*first = *last;
*last = temp;
first++,last--;
}
5.一维指针数组
- 指针数组本质是一个数组,但数组的元素都是相同类型指的指针
// 定义一个整型数组
int a[5]={1,3,4,5};
//定义一个指针数组
int *pa[5]={&a[1],&a[2],&a[3],&a[4],&a[5]};
//遍历指针数组
for(int i = 0; i < 5; i++){
printf("pa[%d] = %p\n",i,pa[i]);
}
//其中
pa[i] == *(pa+i) == &a[i]
*pa[i] == *(*(pa+i)) == a[i]
- 指针变量之间的运算
1).减法运算
//表示两个指针之间相隔了几个元素
// 真实地地址差:(p1-p) * sizeof(int) //12
2)如果 计算结果为负数
//第一个指针变量指向的 在低地址
// 第二个指针变量指向的 在高地址
3)如果结果为 0
// 表示他们指向了同一个地址
6.用数组名访问二维数组
//定义一个二维数组
int a[3][4]={{1,3,5,7}, {9,11,13,15},{17,19,21,23}};
//a+0 a[0] 1 3 5 7
//a+1 a[1] 9 11 13 15
// a[i]+j 代表的是 a[i][j]的地址
// *(a[i]+j) 代表是 a[i][j] 的值
// a[i] *(a+i)
a[i] == a+i
&a[i][j] == *(a+i)+j == a[i]+j
a[i][j] == *(*(a+i)+j)
二维数组比较特殊
// a == a[0] == &a[0][0] == &a[0] == &a
7.用指针访问二维数组
1).用一级指针访问二维数组
//定义一个二维数组
int a[3][4]={{1,3,5,7}, {9,11,13,15},{17,19,21,23}};
// 整形变量的地址
// 1 2
int *p = a;
// 使用一级指针变量p 也可以遍历二维数组,
// 二维数组在内存中是线性存储的
for (int i=0; i<12; i++) {
printf("%d\t",*(p+i));
}
在用一级指针访问二维数组时会有警告,一般不这样使用
2).用二维数组指针访问二维数组
//定义一个二维数组
int a[3][4]={{1,3,5,7}, {9,11,13,15},{17,19,21,23}};
//定义二维数组指针
int (*p)[4] = a;
for (int i=0; i<3; i++) {
for (int j=0; j<4; j++) {
printf("%d\t",*(*(p+i)+j));
}
printf("\n");
}