C语言 数组

一、一维数组

1. 一维数组的创建方式

程序清单1

#include <stdio.h>

int main() {

	int arr1[10] = { 1,2,3,4,5 };
	int arr2[] = { 1,2,3,4,5 };
	int arr3[10];

	return 0;
}

数组 arr1 在定义时,长度给了 10,但初始化未完全。
数组 arr2 在定义时,未明确数组大小,底层根据初始化后提供默认大小。
数组 arr3 只被定义,未初始化,所以底层放的都是随机数字。

1-1

程序清单2

下面的三个数组呈现了字符数组的区别。

这里需要注意 sizeof 和 strlen 的区别,sizeof 求的是整个数组内所有元素占内存的大小( 包括 ’ \0 ’ ),strlen 求的是字符串长度( ’ \0 ’ 之前 )。也就是说,前者求的是数组元素的大小,后者求的是字符串的长度。

#include <stdio.h>
#include <string.h>

int main() {

	char arr4[] = "abcd";
	char arr5[] = { 'a','b','c','d' };
	char arr6[10] = { 'a','b','c','d' };

	printf("%d %d\n", sizeof(arr4), strlen(arr4));
	return 0;
}

// 输出结果:5 4

1-2

2. 一维数组在内存中的存储方式

#include <stdio.h>

int main() {

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

	for (int i = 0; i < size; i++) {
		printf("&arr[%d] => %p\n", i, &arr[i]);
	}
	return 0;
}

输出结果:

1-3

从上面的十六进制的地址来看,我们可以得出结论:

① 一维数组在内存中是连续存放的。
② 随着数组下标的增长,地址由低到高变化。
③ 地址之间的差值,即数组元素类型的大小。( 例如:数组存放的元素是整型,那么每个元素的地址之间就相差 4. )

3. 计算一维数组的元素个数

在 C语言 中,sizeof 可以用来计算某个变量的所占内存的字节大小,所以利用【整个数组所占的内存大小】/ 【数组内某个元素所占的内存大小】,就能够得出数组长度。

#include <stdio.h>

int main() {

	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	printf("%d\n", sizeof(arr)); // 40
	printf("%d\n", sizeof(arr[0])); // 4

	int size = sizeof(arr) / sizeof(arr[0]); // 求数组长度的方法
	printf("%d\n", size); // 10

	return 0;
}

4. 一维数组打印

#include <stdio.h>

// 方法一
void print(int arr[], int size) {

	for (int i = 0; i < size; i++) {
		printf("%d ", arr[i]);
	}
}

// 方法二
void print2(int* arr, int size) {

	for (int i = 0; i < size; i++) {
		printf("%d ", *(arr + i));
	}
}

int main() {

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

	print2(arr, size);

	return 0;
}

arr 为数组名,即首元素地址 &arr[0],其本质上是一个指针。所以我们可以写成方法二的整型指针方式来接收,每次访问数组的元素时,就往后跳一个元素。即跳跃四个字节。

arr[i] <==> *(arr+i)

1-4

二、二维数组

1. 二维数组的创建方式

#include <stdio.h>

int main() {

	int arr1[3][5] = { 0 };
	int arr2[3][5] = { 1,2,3,4,5,6 };
	int arr3[][5] = {1,2,3,4,5,6};
	int arr4[3][5] = { {1,2}, {3,4}, {5,6} };

	//int arr[3][] = { {1,2}, {3,4}, {5,6} }; // error
	return 0;
}

1-5

注意事项:

① 二维数组在创建时,行可以省略,列不可省略。

② 如果提前知道二维数组中存储什么元素,推荐上面的 arr4 (直接初始化);如果提前不确定二维数组的元素,推荐上面的 arr1. (初始化第一行第一列的元素,后面的自动初始化为 0.)

2. 计算二维数组的行和列

和计算一维数组的大小思想相同,这里依旧先采用 sizeof 计算内存所占大小,之后分别计算行和列。

#include <stdio.h>

int main() {

	int arr[3][5] = { {1,2}, {3,4}, {5,6} };
	
	// 整个二维数组的大小 / 第一行一维数组大小
	int row = sizeof(arr) / sizeof(arr[0]); // 60/20 = 3

	// 第一行一维数组大小 / 第一行第一个数组元素的大小
	int column = sizeof(arr[0]) / sizeof(arr[0][0]); // 20/4 = 5

	return 0;
}

3. 二维数组在内存中的存储方式

#include <stdio.h>

int main() {

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

	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < 5; j++) {
			printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);
		}
		printf("\n");
	}
	return 0;
}

输出结果:

1-6

从上面的十六进制地址的输出结果来看,我们可以得出结论:

二维数组在内存中是连续存放的,即二维数组实际的内存是连续存放的,和我们想象中的几行几列不一样。

1-7

4. 二维数组打印

#include <stdio.h>

// 方法一
void print(int arr[3][5], int row, int column) {

	for (int i = 0; i < row; i++) {
		for (int j = 0; j < column; j++) {
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}

// 方法二
void print2(int (*arr)[5], int row, int column) {

	for (int i = 0; i < row; i++) {
		for (int j = 0; j < column; j++) {
			printf("%d ", *(*(arr+i) + j ));
		}
		printf("\n");
	}
}

int main() {

	int arr[3][5] = { {1,2,3,4,5}, {2,3,4,5,6}, {3,4,5,6,7} };
	int row = sizeof(arr) / sizeof(arr[0]); // 行
	int column = sizeof(arr[0]) / sizeof(arr[0][0]); // 列

	print2(arr, row, column);

	return 0;
}

arr 为数组名,本质上描述的是第一行一维数组的地址。此时 arr + i,表示每次跳过一行。所以当我们利用指针的方式作为形参时,这个指针为数组指针。此时数组指针指向数量为 5个元素的 数组。

arr[i][j] <==> *(arr+i)[j] <==> *(*(arr+i)+j)
// 先找行,再找此行的列

1-8

三、数组名的含义

结论

对于一维数组来说,数组名就是首元素的地址。
对于二维数组来说,数组名就是第一行数组的地址。

但有两个例外:

① sizeof(数组名),此时数组名表示整个数组,计算的是整个数组占用内存的大小。
② &数组名,此时数组名表示整个数组,取出的是整个数组的地址。

程序清单

#include <stdio.h>

int main() {

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

	printf("%p\n", arr);
	printf("%p\n\n", arr + 1); // 往后跳 4 个字节

	printf("%p\n", &arr[0]);
	printf("%p\n\n", &arr[0] + 1); // 往后跳 4 个字节

	printf("%p\n", &arr);
	printf("%p\n\n", &arr + 1); // 往后跳 40个字节

	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr[0])); 
	//printf("%d", sizeof(&arr); // error
	
	return 0;
}

输出结果:

1-9

1-10

注意事项:

从上面的四组数据来看,数组名在不同的场景下起到不同的作用。

2-1

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十七ing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值