前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C语言】指针初阶2.0

【C语言】指针初阶2.0

作者头像
s-little-monster
发布2024-06-06 20:42:27
620
发布2024-06-06 20:42:27
举报
文章被收录于专栏:乐意学点小编程

传值调用与传址调用

在开始之前,我们需要先了解这个概念,后面才能够正常的学习

传值调用

代码语言:javascript
复制
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互换大小,再用这样的代码就行不通了

代码语言:javascript
复制
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;
}

我们发现,这样做交换不了两者的值,是因为形参是实参的一份临时拷贝,形参也是有地址的,改变形参影响不了实参,这时我们只能进行传址调用

传址调用

代码语言:javascript
复制
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;
}

这样就能进行调换了,改变实参的值

一维数组与指针

理解数组名

代码语言:javascript
复制
int arr[5] = {1,2,3,4,5};

当我们想要访问arr数组时,我们有一下几种方法

代码语言:javascript
复制
int i = arr[0];
代码语言:javascript
复制
int* p = &arr[0];
代码语言:javascript
复制
int* p = arr;

第一种不必多说,利用访问下标操作符对数组进行访问。第二、三种是我们上一篇文章说的(可移步上一篇:指针初阶),通过指针对数组进行访问,arr与&arr[0]是一样的,都是数组的首元素地址 那我们可能会有疑问了:那&arr是什么样的呢,跟这两个也一样吗?下面我们用编译器来测试下,顺便证明一下第二三种是一样的 打印它们的地址

代码语言:javascript
复制
#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;
}

我们发现它们的地址都是相同的,那它们都相同吗?我们再来看一下

代码语言:javascript
复制
#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,这与我们之前所看到的相悖,我们最后来看一下区别在哪

代码语言:javascript
复制
#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取的是首元素的地址,整个数组是一个整体

使用指针

代码语言:javascript
复制
#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;

数组元素的访问在编译器处理的时候转换成⾸元素的地址+偏移量求出元素的地址,然后解引⽤来访问。

深入理解一维数组

当我们写函数的时候,如果想要改变数组的内容:⼀维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式。 其实这个也是想当然的,因为数组可以用指针来表示,二者等同,那么取而代之肯定也是非常正确的,因为数组的本质就是指针

二级指针

二级指针的概念也很简单,就是存放一级指针的地址的指针

代码语言:javascript
复制
int main()
{
	int i = 10;
	int* pi = &i;
	int** ppi = &pi;
	return 0;
}
代码语言:javascript
复制
*ppi = pi;
**ppi = i;

同理,存放二级指针地址的就是三级指针

指针数组

指针数组就是存放指针的数组,里边每个元素都是地址

代码语言:javascript
复制
int* arr1;//里边的指针类型全部为int*
char* arr2;//里边的指针类型全部为char*

二维数组与指针

代码语言:javascript
复制
#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就到这里了,感谢阅读

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-05-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 传值调用与传址调用
    • 传值调用
      • 传址调用
      • 一维数组与指针
        • 理解数组名
          • 使用指针
            • 深入理解一维数组
            • 二级指针
            • 指针数组
            • 二维数组与指针
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档