C语言-数组详解

目录

1、一维数组的创建和初始化

1.1、数组的创建

1.2、数组的初始化

1.3、一维数组的使用

1.4、一维数组在内存中的存储

2、二维数组的创建和初始化

2.1、二维数组的创建

2.2、二维数组的初始化

2.3、二维数组的使用

2.4、二维数组在内存中的存储

3、数组越界

4、数组作为函数的参数

5、数据实例

5.1、三子棋

5.2、扫雷游戏


1、一维数组的创建和初始化

数组(Array)是有序的元素序列。 若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按有序的形式组织起来的一种形式。 这些有序排列的同类数据元素的集合称为数组。

数组是用于储存多个相同类型数据的集合。

1.1、数组的创建

type_t  arr_name[const_n]

//type_t  是指数组的元素类型

//const_n  是一个常量表达式,用来指定数组的大小

#include <stdio.h>

int main()
{
    //创建整型数组,可以是常量和常量表达式
	int arr1[2+3];
	int arr2[5];

    //字符数组的各种形式
	char ch1[] = "abc";
	char ch2[] = { 'a' ,'b', 'c', '\0'};
	char ch3[] = { 'a' ,'b', 'c' };
	char ch4[3] = { 'a' ,'b', 'c' };
	printf("%s\n", ch1);        
	printf("%s\n", ch2);
	printf("%s\n", ch3);
	printf("%s\n", ch4);

	return 0;
}

输出:

  •  ch1字符串最后有 ‘\0’ 作为字符串的结束标志,所以输出为abc
  •  ch2字符数组需要在最后加上一个 '\0' ,表示遇到 '\0' 结束,否则会打印出乱码
  •  ch3字符数组没有在最后加上 '\0' ,所以会打印出“烫烫烫...”
  •  ch4那么指定数组的大小为3,不在最后加 '\0' 也会出现乱码的情况。

//这样的代码在c99标准之前是不可以的,但是在c99标准之后,允许这样来创建数组,但是不可以初始化。

//vs 2022 不支持变长数组

int n  = 0;

int arr[n];

1.2、数组的初始化

//数组的初始化是指,在创建数组的同时给数组的内容一些合理的初始值(初始化)
int main()
{
	int arr1[5] = { 1, 2, 3 };//不完全初始化
	int arr2[5] = { 1,2,3,4,5 };//完全初始化
	int arr3[] = { 1,2,3,4,5,6,7,8,9,10 };//如果初始化可以不用指定数组的大小

	return 0;
}

1.3、一维数组的使用

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };

    //计算数组元素的个数,数组的大小除以数组每个元素的大小就是元素个数
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < sz; i++)
	{
		//在屏幕上打印数组的元素
		printf("%d ", arr[i]);//[]:是下标引用操作符
	}

	return 0;
}

//输出结果:  1 2 3 4 5 6 7 8 9 10

1.4、一维数组在内存中的存储

int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	for (int i = 0; i < sz; i++)
	{
        //打印出数组每个元素的地址
		printf("&arr[%d] = %p\n", i, &arr[i]);
	}

	return 0;
}

输出:

 我们发现数组在内存中是连续存放的,每个元素的地址加4就是下一个元素的地址,这是因为数组存放的数据类型是int,而int的大小是4个字节。

2、二维数组的创建和初始化

二维数组跟一维数组本质上差不多,可以把二维数组看做是存放一维数组的一维数组,它的每个元素的一维数组。

2.1、二维数组的创建

//二维数组的创建

int arr[2][3];//两行三列的一个整型二维数组

char ch[3][5]; //三行五列的一个字符型二维数组

double arr2[5][6]; //五行六列的双精度浮点型二维数组

2.2、二维数组的初始化

//二维数组的初始化

int arr1[2][3] = {{1,2,3},{4,5,6}};

int arr2[3][4] = {1,2,3,4};

int arr3[][3] = {{1,4},{2,5}};//二维数组如果有初始化,行可以省略不写,但是列不能省略。

2.3、二维数组的使用

//实现二维数组的输入和输出
int main()
{
	int arr1[2][3] = { 0 };
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			//输入值
			scanf("%d", &arr1[i][j]);
		}
	}
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			//打印值
			printf("%d ", arr1[i][j]);
		}
		printf("\n");
	}
	return 0;
}

输出:

 

2.4、二维数组在内存中的存储

int main()
{
	int arr1[2][3] = { {1, 2, 3}, {4, 5, 6} };
	for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			//打印各个元素的地址
			printf("&arr1[%d][%d] = %p\n", i, j, &arr1[i][j]);
		}
	}
	return 0;
}

输出:

可以看出二维数组在内存中的存储也是连续存放的。

3、数组越界

数组的下标是有范围限制的,数组的下标规定是从0开始的,如果数组有n个元素,那么最后一个元素的下标是n-1,所以数组的下标如果小于0,或者大于n-1,那么数组就越界访问了,超出了数组合法空间的访问。

需要注意的是:C语言本身并不做数组下标的越界检查,编译器也不一定报错。

int main()
{
	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
	for (int i = 0; i <= 10; i++)
	{
		printf("%d ", arr[i]);//这里会越界访问,因为数组一共有10个元素,下标为0-9,但是这里会打印arr[10],所以越界了、
	}
	return 0;
}

结果:

 4、数组作为函数的参数

例如我们想要实现一个冒泡排序:

错误代码:

 我们发现并没有达到预期的效果,没有完成升序的排序,这是为什么呢?

因为数组作为函数参数时,数组名是函数首元素的地址,所以bubble_sort函数的参数列表需要一个指针来接收地址,而sizeof(a)计算的是指针的大小,在32位平台上指针的大小是4个字节,在64位平台上指针的大小是8字节,然后sizeof(a[0])相当于计算整型的大小,也是4个字节,所以函数内得到的sz等于1,所以达不到预期的效果。

这里需要特别注意,数组名和数组首元素之间的“羁绊”:

我们似乎发现这三个的地址都一样,但是别被表象误导了。我们试着加1来看一看

 可以得出结论:

  • sizeof(数组名),计算整个数组的大小,sizeof内部单独放一个数组名,数组名表示整个数组。
  • &数组名,取出的是数组的地址,表示整个数组的地址

除了以上两种情况外,所以的数组名都表示数组首元素的地址

//冒泡排序正确代码
void bubble_sort(int a[], int sz)
{
	for (int i = 0; i < sz-1; i++)
	{
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (a[j] > a[j + 1])
			{
				int tmp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = tmp;
			}
		}
	}
}

int main()
{
	int arr[] = { 3, 4, 2, 5, 7, 6, 9, 1, 8, 0 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	bubble_sort(arr, sz);
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

结果:

 5、数据实例

5.1、三子棋

5.2、扫雷游戏

三子棋扫雷代码详见下期更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值