c语言自学教程——数组(后篇)

133 阅读1分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

目前在不断更新《c语言自学教程》
未来会讲到《数据结构算法》,《C++语言》,《Linux系统编程》,《Linux网络编程》,《MySQL数据库》等。
期待系统学习编程的小伙伴可以关注我,不错过!

1. 数组越界

数组的下标是有范围限制的。
数组的下规定是从0开始的,如果数组有n个元素,最后一个元素的下标就是n-1。 所以数组的下标如果小于0,或者大于n-1,就是数组越界访问了,超出了数组合法空间的访问。
C语言本身是不做数组下标的越界检查,编译器也不一定报错,但是编译器不报错,并不意味着程序就是正确的,
二维数组的行和列也可能存在越界。
所以程序员写代码时,最好自己做越界的检查

#include <stdio.h>
int main()
{
    int i = 0;
    int arr[] = {1,2,3,4,5,6,7,8,9,10};
    for(i=0; i<=12; i++)//在这里数组越界访问了,但这是主要问题吗?
    {
        arr[i] = 0;
        printf("haha\n");
    }
    return 0;
}

让我们公布答案吧!
这段代码的bug是死循环
很抱歉满屏的haha吵到了你的眼睛(手动狗头)
是不是难以想象?请带着疑惑看看下文解释

有以下几个规则:

  1. i和arr是局部变量
  2. 局部变量是放在栈区上的
  3. 栈区上内存的使用习惯是:先使用高地址处空间再使用地地址处空间
  4. 数组随着下标的增长,地址由低到高变化

示意图如下

“由低到高”和“由高到低”相遇了。
arr [12] = 0;  间接改变了i,相当于i = 0;
这样一来i又从0依次变大再回归0,实现了死循环的局面

至于空白格子代表的局部变量储存时相间隔的的字节个数是如何确定的,
这得看不同编译器了。vs编译器是空两格,其他编译器是什么样的,感兴趣可以自己探索哦。

2. 数组作为函数参数

2.1 冒泡排序函数的错误设计

冒泡排序的核心思想:
相邻的两元素进行比较,有需要的话就交换

\

//错误代码
void bubble_sort(int arr[])
{
	int sz = sizeof(arr)/sizeof(arr[0]);//这样对吗?
	int i = 0;
	for(i=0; i<sz-1; i++)//sz-1趟冒泡排序
	{
		int j = 0;
		for(j=0; j<sz-i-1; 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,7,5,8,9,0,2,4,6};
	bubble_sort(arr);//是否可以正常排序?
	for(i=0; i<sizeof(arr)/sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

2.2 数组名是什么?

数组传参的实质不是传整个数组,而是首元素的地址
bubble_sort函数中的sizeof(arr)算出的是指针的大小,因此导致错误
arr本质是首元素地址,数组接收时也可以用int *arr代替int arr[]

特殊情况:

  1. &arr


2. sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组

2.3 冒泡排序函数的正确设计

void bubble_sort(int arr[], int sz)//参数接收数组元素个数
{
	//代码同上面函数
	int i = 0;
	for(i=0; i<sz-1; i++)//sz-1趟冒泡排序
	{
		int j = 0;
		for(j=0; j<sz-i-1; 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,7,5,8,9,0,2,4,6};
	int sz = sizeof(arr)/sizeof(arr[0]);
	bubble_sort(arr, sz);//是否可以正常排序?
	for(i=0; i<sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

这次以冒泡排序为例,初步讲解了数组作为函数参数的用法,以后还会遇到,大家要多多理解一下这里哦。