梓喵出没

喵喵喵

复习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这个老祖宗倒是快忘的一干二净了。

引用资料

1.[网页]博客园C语言中数组名和指针的区别

我来吐槽

*

*

5位绅士参与评论

  1. 岁月小筑08-26 08:46 回复

    233333,你这命名很6啊,maoPao,有点反X人X类啊(捂脸)

  2. 欣欣08-08 13:22 回复

    只会c++的路过 喵呜 加油

  3. c0smxsec08-02 21:31 回复

    学C大佬

  4. C#不是包含了c语言的一些内容吧,对于这些在C#也会使用吧?

    • 野兔07-20 17:11 回复

      机器码生汇编,汇编生C,C生万物。