数组作函数参数的退化问题
昨天真是气得慌,刚写完这个,提交的时候,浏览器竟然崩了,大半夜的第二天又有课,于是就拖到今天才写了。
续借前题,我之前说过写完内存四区之后,会开始讲关于指针的问题,然而一看题目似乎与指针并没有多大关系,而我说的内存四区估计大家也是看到一脸懵,这一点我确实没怎么写好,但是正如定义那样,写代码的时候,大家可以在脑海中建立内存四区模型。
为什么我要这么说,因为什么是指针?指针是通过存储的地址来操作内存空间,也就是说我们想要操作这块内存空间才使用了指针,这样的话,我们总得知道我们操作的空间属于哪一块吧!或者说它有什么属性吧!要不然我们连指针指向哪里都不知道,我们要这指针又有什么用!
指针:通过储存的地址来操作内存空间
先来个例一
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void disrtibution_01(int a)// 空函数是不用return的
{
a = 100;
}
void distribution_02(int *a)
{
*a = 200;//同过指针改变实参的值
}
int main()
{
int a = 10;
disrtibution_01(a);//将数值传递给形参
printf("%d\n",a);//我们发现数值并未改变 a = 10
distribution_02(&a);//将地址传递给指针
printf("%d\n",a);//我们发现数值改变 a = 200
return 0;
}
在这里我们发现,同样是void型函数:仅仅想通过传递值来改变实参是无法做到的,然而却可以通过差传递地址将值改变,也就是指针可以通过操作内存空间来修改里面的数值,先这样理解:指针是可以改变所指向的变量的值的;
例子二:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void sortArray(int a[4])//排序
{
int i = 0;
nt j = 0;
int tmp = 0;//辅助变量
printf("sizeof(a):%d\n",sizeof(a));//a占4个字节
//冒泡排序法
//由小到大排序
for(i = 0; i < 4; i++)
{
for(j = i+1; j < 4; j++)
{
if(a[i] > a[j])//如果前面的数大于后面的数则交换 a[i] 和 [j] 比较
{
tmp = a[i];//将a[i] 的值赋给tmp
a[i] = a[j];//将后面较小的数值赋给前面
a[j] = tmp;//将前面较大的数值赋给后面
}
}
}
}
void sortArray2(int a[],int num)
{
int i = 0;
int j = 0;
int tmp = 0;//辅助变量
printf("sizeof(a):%d\n",sizeof(a));//a占4个字节
//冒泡排序法
//由大到小排序
for(i = 0; i < num; i++)
{
for(j = i+1; j < num; j++)
{
if(a[i] < a[j])//如果前面的数大于后面的数则交换 a[i] 和 [j] 比较
{
tmp = a[i];//将a[i] 的值赋给tmp
a[i] = a[j];//将后面较大的数值赋给前面
a[j] = tmp;//将前面较小的数值赋给后面
}
}
}
}
void sortArray3(int *a,int num)
{
int i = 0;
int j = 0;
int tmp = 0;//辅助变量
printf("sizeof(a):%d\n",sizeof(a));//a占4个字节
//冒泡排序法
//由小到大排序
for(i = 0; i < num; i++)
{
for(j = i+1; j < num; j++)
{
if(a[i] > a[j])//如果前面的数大于后面的数则交换 a[i] 和 [j] 比较
{
tmp = a[i];//将a[i] 的值赋给tmp
a[i] = a[j];//将后面较小的数值赋给前面
a[j] = tmp;//将前面较大的数值赋给后面
}
}
}
}
void printfArray(int a[4])//打印数组
{
int i = 0;
for(i = 0 ; i < 4; i++)
{
printf("%d ",a[i]);
}
printf("\n");
}
int main()
{
int i = 0,j = 0;
int tmp = 0;
int num = 0;
int a[] = {22,33,4,333};//一维数组 4 * 4 = 16
num = sizeof(a)/sizeof(a[0]);//数组的下标是从0开始的
printf("sizeof(a):%d\n",sizeof(a));//计算分配的内存空间大小 16
sortArray(a);
printf("第一个函数排序打印:");//4 22 33 333
printfArray(a);
sortArray2(a,num);
printf("第二个函数排序后打印:");//333 33 22 4
printfArray(a);
sortArray3(a,num);
printf("第三个函数排序后打印:");//4 22 33 333
printfArray(a);
system("pause");
return 0;
}
在这里为了给数组里的值排序我用来三个函数sortArray(int a[4]), sortArray2(int a[],int num), sortArray3(int *a,int num);
我们发现sortArray(int a[4])和例子一里的disrtibution_01(int a)似乎很相似,但是这里对数组的排序竟然成功了;这说明 这个int a[4]和int a是不同的;
首先看main函数int a[] = {22,33,4,333};//一维数组里我们分配了 4 * 4 = 16 字节的内存空间
但是在三个子函数中我们都发现,他们所占的内存只有4 个字节,这里我们要知道所有的指针只占四个字节的内存空间,不管是一级指针还是十级指针,所以数组作参数时我们发现,他们所占的内存空间和指针是一样的;也就是说调用的时候并没再次给他们分配 16 字节的内存空间;
而且我们发现三个函数参数是这样变化的:int a[4] ==>int a[] ==>int *a;而且它们都运行成功了:
于是我们就得出这么一个结论:
数组作参数时编译器自动将它们退化为了指针;而指针通过地址找到内存空间并对其进行操作;
可能很多人看完之后还是很不解,这是很正常的,我刚开始学的时候也是这样,于是通过不断的翻阅资料,不断的敲代码,才开始逐渐理解,指针被称为c的灵魂,自然不可能是这么一言两语就能说完,所以接下来的日子我会把我对指针的见解逐渐分享给大家,希望可以互相交流,共同提高;