C语言指针的相关知识(2023.09.08)

每天学习进步一点,收获多一点。

六、数组作为函数参数

首先来看下面这个程序:下面这个程序实现了计算一个数组元素总和的功能,但是需要通过传递“size”才能实现。那么如何修改代码,在不将数组大小作为额外参数传递的前提下实现相同功能呢?

#include<stdio.h>
int SumOfElements(int A[],int size)
{
	int i,sum = 0;
	for(i=0;i<size;i++)
	{
	sum=sum+A[i];
	}
	return sum;
}

int main()
{
	int A[]={1,2,3,4,5};
	int size=sizeof(A)/sizeof(A[0]);
	int total=SumOfElements(A,size);
	printf("The Sum Of Elements is %d\n",total);
}

来看下面这段程序:

#include<stdio.h>
int SumOfElements(int A[])
{
	int i,sum = 0;
	int size=sizeof(A)/sizeof(A[0]);
	printf("SOE-Size of A = %d,size of A[0] = %d\n",sizeof(A),sizeof(A[0]));
	for(i=0;i<size;i++)
	{
	sum=sum+A[i];
	}
	return sum;
}

int main()
{
	int A[]={1,2,3,4,5};
	int total=SumOfElements(A);
	printf("The Sum Of Elements is %d\n",total);
	printf("Main-Size of A = %d,size of A[0] = %d",sizeof(A),sizeof(A[0]));
}

当运行这段程序后,程序的结果如下:

可以看到,程序的结果并不是我们想要的,在SOE函数中,Size of A只有4个字节,而在main函数中却有20个字节,同时元素的和也不对。为了解释这个问题,我们需要深入了解计算机是如何解释数组作为函数参数这件事。

为了执行函数,我们使用使用内存中的栈,当程序开始执行时,系统将栈上的一部分内存分配给main函数,在栈上开辟的这部分内存也被称为栈帧,其中存储了所有的局部变量。在理想条件下,首先在开辟的栈帧中,将给数组A[]开辟20个字节的存储单元,给变量total开辟4个字节的存储单元。当进行函数调用时,系统给SOE函数开辟栈帧,同时数组A[]作为形参传递,在栈帧中同样开辟20个字节的存储单元。但是实际情况是:当数组作为函数参数时,并不会拷贝整个数组,而是创建一个同名的指针,而这个指针所占的存储空间与变量同类型,也就是4个字节。编译器将仅仅拷贝主调函数数组首元素的地址。

所以在上面的程序中,应该将SumOfElements函数修改为:int SumOfElements(int *A,int size)

七、指针和字符数组

指示字符数组结束的标志:'\0',

假设我们定义一个字符数组:char C1[6]="Hello";再定义一个字符指针:char *C2;那么当我们直接写C2=C1;时,这个语句是合法的,C2内将储存C1数组的首字符的地址,实际上,当我们执行语句C2[I]时,实际执行的是C2[i]=*(C2+i)。

当数组作为函数参数的时候,实际上传输的只是函数的基地址,而不是传输整个数组的拷贝。

八、指针和二维数组

当我们创建一维数组时,例如声明一个5个元素的数组A[5],实际上就是在一块连续的内存上创建了A[1]~A[4]。

事实上,*(A+i)与A[i]是相同的,(A+i)与&A[i]也是相同的。

回到二维数组,当我们创建一个二维数组B[2][3],实际上是创建了两个一维数组,每一个一维数组中有3个整形元素。

在这种情况下,由于数组名返回数组首元素的指针,而因为这次元素不是一个整形,而是包含三个整形的一维数组,所以当执行语句:int *p=B;那么系统将会报错,因为B返回的是一个指向一维数组的指针,而不是一个整形的指针。正确的写法是:int (*p)[3]=B;

当执行与语句:printf B;或 &B[0]时,都是打印B[0][0]的地址,也就是400。如果执行printf *B;或B[0];或者&B[0][0],同样是打印B[0][0],即400。

而当执行B+1的指令时,将会移动到B[1],即412的位置。

*(B+1)/B[1]/&B[1][0]都是相同的意思,即B[1][0]的地址412,那么*(B+1)+2的值是什么呢?

答案是:412+8=420,即B[1][2]的地址。

九、指针和多维数组

多维数组本质上是数组的数组。数组基本上可以理解为同类型事物的集合,而多维数组基本上可以理解为数组的集合。

B[i][j]=*(B[i]+j)=*(*(B+i)+j)

现在,假设有一个三维数组C[3][2][2],那么他在内存中的储存顺序是这样的:

C[i][j][k]=*(C[i][j]+k)=*(*(C[i]+j)+k)=*(*(*(C+i)+j)+k)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值