C语言边界计算和不对称边界

本文探讨了C语言为何设定数组下标从0开始,揭示了这一设计背后的‘不对称边界’原则,通过实例说明如何避免常见的‘栏杆错误’,并展示了编程中如何利用这种设计减少错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

栏杆错误(“差一错误”)

100英尺的长的围栏,每隔10英尺就需要一根支撑用的栏杆,共需要多少栏杆?

最“显而易见”的答案就是100/10,得到的结果是10,也就是需要10根栏杆。但这个结果是错的,争取答案是11。
思考方法:

  1. 要支撑10英尺长的围栏实际上需要两根栏杆,两端各一根。
  2. 除了最右端的一段栏杆,其他每一段10英尺长的围栏都只有左侧有一根栏杆;而例外的最右侧一段围栏不仅左侧有一根栏杆,右侧也有一根栏杆。

所以就总结出了两个避免“栏杆错误”的通用原则。

  1. 首先考虑最简单的情况下的特立,然后将得到的结果外推,这是原则一。
  2. 仔细计算边界,绝不掉以轻心,这是原则二。

各语言有关数组上下界的设定

如果有一个数组有10个元素,那么这个数组下标的允许取值范围是什么?

在Fortran,PL/I以及Snobol4等编程语言,数组的下表取值是从1开始,而Algol和Pascal等语言,数组下表没有缺省的起始值,编程人员必须指每个数组的下界和上界。在标准的Basic语言中,声明一个10个元素的数组,实际上编译器分配了11个元素的空间,下标范围从0-10。
但是在C语言中,这个数组的下标范围是从0到9。在一个拥有10个元素的数组中,存在下标为0的元素,却不存在下标为10的元素。在C语言中,一个拥有n个元素的数组,同样也没有下标为n的元素。

那么为什么C语言要用和常人理解不一样的方式去定义一个数组?
别急,先看看不对称边界的例子

不对称边界与“栏杆错误”

定义

“不对称边界”是将“下界上界问题”转为“入界和出界问题”,将下界作为“入界点”包括在取值范围之内,而“出界点”在下界之后,不包括在取值范围内。如X>=16且X<38,入界点“16”包括在取值范围之内,而“38”是出界点,不包括在取值范围之内。

假定一个整数x满足边界条件x >= 16且x <=37,那么此范围内x可能有多少个取值?
换句话说,整数序列16,17,18,…,36,37共有多少个元素?很显然,答案与37-16非常接近,那么到底答案是20,21还是22?

根据原则一,我们考虑最简单的特例。这里假设整数x的取值范围是x >= 16且x <= 17,很显然整数x的取值有两个(17 - 16 + 1),然后再将特例向外推,那么x >= 16且x <=37就是,37 -16 + 1。
再根据原则二,再次计算一次,得到的结果确实是(37 -16 + 1)。
造成“栏杆错误”的根源就是“37 -16 + 1”的“+1”


那么有没有一种编程技巧去降低这种错误的发生?
有,并且C语言就很好的避免了这个问题

用第一个入界点和第一个出界点来表示一个数值范围。

比如同样的取值范围,就写成x >= 16且x < 38,那么结果就直接是38 -16了,结果同样是22.

注意:这里的下界点是“入界点”,即包括在取值范围内的;而上界就是“出界点”,是不包括在取值范围内的。

虽然这种“不对称”也许从数学上不太美观,或者是从习惯上不太习惯,但是它对于程序设计的简化效果却足以让人吃惊。
比如像C语言这种设定数组从0开始设定,不对称边界的设计带来的方便就极为明显:这种数组的上界(第一个“出界点”)恰好就是数组元素的个数!因此,如果要在C语言中定义一个10个元素的数组,0就是“入界点”(在数组下标范围内的点,包括边界点),10就是“出界点”(不在数组下标范围内的点,不含边界点),代码实现如下

int i = 0;
	int arr[10] = { 0 };
	for (i = 0; i < 10; i++)
	{
		arr[i] = 0;
	}

而不是写成

int i = 0;
	int arr[10] = { 0 };
	for (i = 0; i <= 9; i++)
	{
		arr[i] = 0;
	}

我们再回到开头,C语言设定数组下标从0开始不是随便设置的,而是为了简化程序,避免程序出现“栏杆问题”等其他问题

所以说,C语言被称为“最灵活的语言之一不是没有原因的”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值