C语言教程——数组(2)

目录

系列文章目录

前言

4、数组作为函数参数

4.1冒泡函数的错误设计

4.2数组名是什么?

总结


前言

我们知道一维数组是连续存放的,随着数组下标的增长,地址是由低到高依次存放的,二维数组,也是在内存里面是连续存放的,而且要检查数组是否越界。


4、数组作为函数参数

往往我们在写代码的时候,会将数组作为参数传入函数,比如:我要写一个冒泡函数(这里要讲算法思想)函数,将一个整形数组排序。

排序的思想和方法有很多,例如冒泡排序,选择排序,插入排序,快速排序等等。

冒泡排序的思想就是两辆元素进行比较,有可能的话需要交换。

比如我们要对一组整形数据进行排序,要排成升序:

9 8 7 6 5 4 3 2 1 0

如果我们有十个数字,那么会需要9趟则可以完全排序,如果有n个数字,那么就需要n-1趟。两个一比较,就可以通过下标来访问元素。

cpp 复制代码
#include <stdio.h>
//排序:
void Sort(int arr[],int sz)
{
	
	int i = 0;
	//趟数
	for (i = 0; i < sz - 1; i++)
	{
		//一趟冒泡排序,决定了一趟排序进行了多少对比较
		int j = 0;
		for (j = 0; j < sz-1-i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

int main()
{
	//整形数据
	int arr[] = { 3,1,4,2,9,8,6,5,7,0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	//写一个函数对数组进行排序
	Sort(arr,sz);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

以上代码就是升序排序1-0。

4.1冒泡函数的错误设计

再看看下面的代码:

cpp 复制代码
#include <stdio.h>
//排序:
void Sort(int arr[])
{
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	//趟数
	for (i = 0; i < sz - 1; i++)
	{
		//一趟冒泡排序,决定了一趟排序进行了多少对比较
		int j = 0;
		for (j = 0; j < sz-1-i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
}

int main()
{
	//整形数据
	int arr[] = { 3,1,4,2,9,8,6,5,7,0 };
	
	//写一个函数对数组进行排序
	Sort(arr);
	int i = 0;
	for (i = 0; i < 10; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

这是一个错误的冒泡函数编写格式,这里面打印出的数组并没有发生排序,而是原封不动的给你打印出来。我们可以先放着这个问题,来进行下面的介绍和学习,相信看完和理解后就会知道为什么数组没有排序了。

4.2数组名是什么?

我们先定义一个里面数字都为0的数组:

cpp 复制代码
int main( )
{
    int arr[10]={0};
    printf("%p\n",arr);
    printf("%p\n",&arr[0]);


    return 0;
}

这里输出的是一个地址,每次运行都不一样,因为分配的内存每次编译是不一样的。

第一行输出的是数组名的地址,第二行输出的是数组首元素的地址,运行出来就可以发现,它们两个都是一个地址,所以得出结论,数组名是数组首元素的地址。

但是有两个例外

1、sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节。

2、&数组名,这里的数组名是表示整个数组,取地址数组名取出的是数组的地址。

我们可以通过以下代码更能直观的看出来:

cpp 复制代码
int main( )
{
    int arr[10]={0};
    printf("%p\n",arr);
    printf("%p\n",arr+1);

    printf("%p\n",&arr[0]);
    printf("%p\n",&arr[0]+1);

    printf("%p\n",&arr);
    printf("%p\n",&arr+1);

    return 0;
}

首先定义一个里面有10个0的数组,通过打印数组名和&数组名来分析。

我们知道数组名的话,是代表数组的首元素,所以前两个打印出来的一个是首元素的地址,另一个是第二个元素的地址,+1与首元素差了4个字节;中间的&arr[0],用下标来访问,也是一样的首元素的地址,第二个与它也差4个字节;最后两行输出,&arr虽然说是代表整个数组,但是整个数组是从首元素开始的,当&arr+1的时候,它们之间就差了40个字节,因为这个数组元素为十个且为整形,4*10=40,由此可以说明&arr代表了一整个数组。

其实指针+1,到底跳过几个字节,是和指针类型有关系的,后面会进行讲解。

了解这些后就可以回到上一篇文章去分析冒泡排序的函数。

数组传参的时候形参写成数组还是指针都是可以的。

我们可以知道函数调用的时候,参数传入的时候是对实参的一份临时拷贝,所以数组本质上传参是数组首元素的地址而已。

下一篇讲三子棋的实现,数组的实例。


总结

数组名实际上就是一个地址,传入参数就相当于传入的是数组的首元素的地址,当用到取地址+数组名的时候才是整个数组。

相关推荐
Ajiang282473530416 分钟前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
幽兰的天空21 分钟前
Python 中的模式匹配:深入了解 match 语句
开发语言·python
Theodore_10223 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
网易独家音乐人Mike Zhou4 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
----云烟----5 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024065 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
开心工作室_kaic6 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
向宇it6 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
武子康6 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
转世成为计算机大神6 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式