复习C这个老祖宗,写了个简单的冒泡排序,想实现将整型数组内的元素从小到大排列,结果出了点小问题。经查阅资料发现数组名这个东西还挺有意思的。
喵喵喵
问题复现
平时都是把数组名当作特殊的指针来用的,所以开始是这么写的。
int * maoPao(int *a);
int main()
{
int a[5] = {21,3,12,9,5};
int *p = maoPao(a);
printf("%d %d %d %d %d",p[0],p[1],p[2],p[3],p[4]);
}
int * maoPao(int *p)
{
int len = sizeof(p)/sizeof(p[0]);
printf("数组元素个数%d\r\n",len);
//冒泡排序
for(int i = 0;i < len - 1; i++)
{
int flag = 1;
for(int j = 0 ;j < len - 1 -i;j++)
{
if(p[j] > p[j+1])
{
int t = p[j];
p[j] = p[j+1];
p[j+1] = t;
flag = 0;
}
}
if(flag)
{
break;
}
}
//void也可以,因为操作的都是指针对应的内容,a数组的值已经变了。
return p;
}
运行结果:
数组元素个数2
3 21 12 9 5
这就不对了,数组元素明明是5个,怎么变成2个了呢?冒泡的结果也是不正确的。
之后依次尝试输出sizeof(p)与sizeof(p[0]),运行结果: 8 4
我一个数组,怎么就变成了一个普的指针变量了呢?
解决问题
经查,有言:数组名作为函数形参时,在函数体内,失去了本身的内涵,仅仅只是一个指针。同时它还失去了其常量特性,可以自增,自减等,可以被修改。
数组名本质的三个结论:
1、数组名的内涵在于其只带实体是一种数据结构,这种数据结构就是数组。
2、数组名的外延在于其可以转换为指向其指代实体的指针,而且是一个指针常量。
3、指向数组的指针则是另外一种变量类型,指针变量,仅仅意味着数组的存放地址。
因此,这里通过sizeof相除得到数组元素个数的方法在main函数里正常,但若是通过形参传递到其他函数体里,这里的形参只是一个普通的指针变量,结果就不再正确了。
所以,将数组长度作为参数与数组一起传递给处理函数即可。
处理函数修改为:
int * maoPao(int *p,int arrLen)
{
int len = arrLen;
printf("数组元素个数%d\r\n",len);
//冒泡排序
for(int i = 0;i < len - 1; i++)
{
int flag = 1;
for(int j = 0 ;j < len - 1 -i;j++)
{
if(p[j] > p[j+1])
{
int t = p[j];
p[j] = p[j+1];
p[j+1] = t;
flag = 0;
}
}
if(flag)
{
break;
}
}
//void也可以,因为操作的都是指针对应的内容,a数组的值已经变了。
return p;
}
对应修改函数调用及声明即可。
运行结果:
数组元素个数5
3 5 9 12 21
平时用惯了java c#之类的,对c这个老祖宗倒是快忘的一干二净了。
引用资料