数组越界及动态数组

数组越界问题

在 C 语言中,数组必须是静态的。换而言之,数组的大小必须在程序运行前就确定下来。
然而,在 C 语言中,为了提高运行效率,给程序员更大的空间,为指针操作带来更多的方便,C 不检查数组下标的取值是否在合法范围内,也不检查数组指针是否移出了数组的合法区域。
因此,在编程中使用数组时就必须格外谨慎,在对数组进行读写操作时都应当进行相应的检查,以免对数组的操作超过数组的边界,从而发生缓冲区溢出漏洞。(当然VS等现代编译器会警告数组越界,但是不会报错)
在这里插入图片描述
最近在做题时遇到了两个数组越界相关的问题,做一个整理。

1,粗心引起的越界
这道题写错的数组的长度(5写成6)导致输出出错。

#include<stdio.h>
int main()
{
	int a[5] = { 1,2,3,4,5 };
	for (int i = 0; i < 6; ++i)//写错了数组的长度
	{
		printf("%d ", a[i]);
	}
	return 0;
}

在这里插入图片描述

2,sizeof引起的越界

从表面看,sizeof(a) / sizeof(a[0])计算数组的长度,代码的输出结果应该是“0,1,2,3,4”,但实际结果却出乎我们的意料,如下图。

#include<stdio.h>

void test(int a[])
{
	for (int i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
	{
		a[i]=i;
	}
}
int main()
{
	int a[5];
	test(a);
	for (int i = 0; i < sizeof(a) / sizeof(a[0]); ++i)
	{
		printf("%d ", a[i]);
	}
	return 0;
}

在这里插入图片描述
在main函数中定义了int a[5];a代表的是整个数组(int a[5]);因此sizeof(a)=sizeof(int*)=20,在main函数中是可以计算出数组的长度。
在这里插入图片描述
然而用数组名作函数参数时,不是进行值传送而是地址传送,编译器传入的是数组的指针,它是一个int型指针(int * ),因此sizeof(a)=sizeof(int*)=4;而sizeof(a[0])=4,导致sizeof(a) / sizeof(a[0])=1。
这样test函数执行后在main函数中就出现了数组越界。
在这里插入图片描述

如何避免

显式地指定数组的边界

可以使用宏的形式来显式指定数组的边界

#define MAX 10
int a[MAX]={1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < MAX; ++i)//避免了错误
{
	printf("%d ", a[i]);
}

不用sizeof计算指针长度

可以通过传入数组的长度的方式来解决这个问题

利用动态数组根据需要分配内存

在 C 语言中,数组必须是静态的。换而言之,数组的大小必须在程序运行前就确定下来。无法直接输入常数来分配数组内存。

printf("请输入数组长度:");
scanf_s("%d", &size);
int a[size];

在这里插入图片描述
动态数组提供了一种解决思路
动态数组可以·在程序运行阶段根据实际需要来分配内存空间的,而不是在编译阶段确定数组内存。这样做能够做到按需分配,而不浪费系统资源。主要应用在事先不知道数组的元素的情况下,需要在程序运行阶段按照实际的外部输入的数据才能确定数组大小的情况。

printf("请输入数组长度:");
scanf("%d", &size);
arr = (int*)malloc(size * sizeof(int));
//以一维数组为例,展示动态数组的建立
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

void test(int* arr,int size)
{
	for (int i = 0; i < size; i++) {
		arr[i] = i;
	}
	printf("\n打印数组元素:\n");
	for (int i = 0; i < size; i++)
		printf("%d\t", arr[i]);
}
int main() {
	int* arr = NULL, size;
	printf("请输入数组长度:");
	scanf_s("%d", &size);
	arr = (int*)malloc(size * sizeof(int));
	if (arr == NULL) {
		printf("内存申请失败!");
		exit(1);
	}
	test(arr, size);
	free(arr);
	
	arr = (int*)malloc(2 * size * sizeof(int));
	if (arr == NULL) {
		printf("内存申请失败!");
		exit(1);
	}
	test(arr, 2 * size);
	free(arr);
	return 0;
}

在这里插入图片描述
参考:
https://www.cnblogs.com/linxw-blog/p/10907557.html.
http://c.biancheng.net/view/366.html.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

燕南路GISer

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

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

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

打赏作者

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

抵扣说明:

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

余额充值