这篇博文我们来继续学习指针的其他内容
指针2.0
- 传值调用与传址调用
- 传值调用
- 传址调用
- 一维数组与指针
- 理解数组名
- 使用指针
- 深入理解一维数组
- 二级指针
- 指针数组
- 二维数组与指针
传值调用与传址调用
在开始之前,我们需要先了解这个概念,后面才能够正常的学习
传值调用
int add(int x, int y)
{
return x + y;
}
int main()
{
int a = 10;
int b = 20;
int c = add(a, b);
printf("%d", c);
return 0;
}
经典的传值调用,只需要传值即可,没有过多的要求,但如果我们的要求是将ab互换大小,再用这样的代码就行不通了
void ecn(int x, int y)
{
int tmp = x;
x = y;
y = tmp;
}
int main()
{
int a = 10;
int b = 20;
ecn(a, b);
printf("a = %d\n", a);
printf("b = %d\n", b);
return 0;
}
我们发现,这样做交换不了两者的值,是因为形参是实参的一份临时拷贝,形参也是有地址的,改变形参影响不了实参,这时我们只能进行传址调用
传址调用
void ecn(int* x,int* y)
{
int tmp = *x;
*x = *y;
*y = tmp;
}
int main()
{
int a = 10;
int b = 20;
ecn(&a, &b);
printf("a = %d\n", a);
printf("b = %d\n", b);
return 0;
}
这样就能进行调换了,改变实参的值
一维数组与指针
理解数组名
int arr[5] = {1,2,3,4,5};
当我们想要访问arr数组时,我们有一下几种方法
int i = arr[0];
int* p = &arr[0];
int* p = arr;
第一种不必多说,利用访问下标操作符对数组进行访问。第二、三种是我们上一篇文章说的(可移步上一篇:指针初阶),通过指针对数组进行访问,arr与&arr[0]是一样的,都是数组的首元素地址
那我们可能会有疑问了:那&arr是什么样的呢,跟这两个也一样吗?下面我们用编译器来测试下,顺便证明一下第二三种是一样的
打印它们的地址
#include <stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5 };
printf("&arr[0] = %p\n", &arr[0]);
printf("arr = %p\n", arr);
printf("&arr = %p\n", &arr);
return 0;
}
我们发现它们的地址都是相同的,那它们都相同吗?我们再来看一下
#include <stdio.h>
int main()
{
int arr[5] = { 1,2,3,4,5 };
printf("%d\n", sizeof(arr));
return 0;
}
如果它们都相同,那么sizeof(arr)与sizeof(arr【0】)应该相同,那应该在32位下为4,只有整个数组的大小才为20,这与我们之前所看到的相悖,我们最后来看一下区别在哪
#include <stdio.h>
int main()
{
int arr[5] = { 1,2,3,4,5 };
printf("&arr[0] = %p\n", &arr[0]);
printf("&arr[0]+1 = %p\n", &arr[0] + 1);
printf("arr = %p\n", arr);
printf("arr+1 = %p\n", arr + 1);
printf("&arr = %p\n", &arr);
printf("&arr+1 = %p\n", &arr + 1);
return 0;
}
我们可以看到&arr+1跟另外两个不同,地址加了20,而另外两个加了4;正如我们所想,arr确实代表着一个数组,但&arr取的是首元素的地址,整个数组是一个整体
使用指针
#include <stdio.h>
int main()
{
int arr[5] = { 0 };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
int* p = arr;
for (i = 0; i < sz; i++)
{
scanf("%d", p + i);
}
for (i = 0; i < sz; i++)
{
printf("%d ", p[i]);//这里*(p+i)=p[i]
}
return 0;
数组元素的访问在编译器处理的时候转换成⾸元素的地址+偏移量求出元素的地址,然后解引⽤来访问。
深入理解一维数组
当我们写函数的时候,如果想要改变数组的内容:⼀维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式。
其实这个也是想当然的,因为数组可以用指针来表示,二者等同,那么取而代之肯定也是非常正确的,因为数组的本质就是指针
二级指针
二级指针的概念也很简单,就是存放一级指针的地址的指针
int main()
{
int i = 10;
int* pi = &i;
int** ppi = π
return 0;
}
*ppi = pi;
**ppi = i;
同理,存放二级指针地址的就是三级指针
指针数组
指针数组就是存放指针的数组,里边每个元素都是地址
int* arr1;//里边的指针类型全部为int*
char* arr2;//里边的指针类型全部为char*
二维数组与指针
#include <stdio.h>
int main()
{
int arr1[5] = { 1,2,3,4,5 };
int arr2[5] = { 2,3,4,5,6 };
int arr3[5] = { 3,4,5,6,7 };
int* parr[3] = { arr1, arr2, arr3 };
//我们一般把p作为指针变量,后面加上arr表示是数组指针变量,有关于数组指针变量的知识我们下期再分享
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 5; j++)
{
printf("%d ", parr[i][j]);
}
printf("\n");
}
return 0;
}
我们看到很熟悉的parr[ i ][ j ]的形式,这其实就是二维数组的真正形态,在运行时二维数组也是要先变成指针的形式再进行运算的,所以说数组的本质是指针
这篇2.0就到这里了,感谢阅读