C語言中的邊界計算與不對稱邊界(二)

2021-06-22 15:42:40 字數 1913 閱讀 5318

儘管c語言的陣列會讓新手感到麻煩,然而c語言中陣列的這種特別的設計正是其最大優勢所在。要理解這一點,以下是一些簡單解釋。

在所有常見的程式設計錯誤中,最難於察覺的一類是「欄杆錯誤」,也常被稱為「差一錯誤」(off-by-one error)。例如這個問題:100英呎長的圍欄每隔10英呎需要一根支撐用的欄杆,一共需要多少根欄杆呢?如果不加思索,大家會容易以為是100除以10,即為10根。其實,真正需要的是11根。

因為支撐10英呎長的圍欄實際需要2根欄杆,即兩端各一根。這個問題的另一種思考方式是,除了最右側的一段圍欄,其他每一段10英呎長的圍欄都只在左側有一根欄杆;而例外的最右側一段圍欄不僅左側有一根欄杆,右側也有一根欄杆。

為了避免以上問題中所說的「欄杆錯誤」,以下是兩個注意的通用原則:

(1)首先考慮最簡單情況下的特例,然後將得到的結果外推;

(2)仔細計算邊界,絕不掉以輕心;

將上面這兩點牢記住以後,現在看看整數範圍的計算。例如,假定整數x滿足邊界條件x>=16且x<=37,那麼此範圍內的x的可能取值個數有多少?即16到37之間一共有多少個元素?很顯然,答案與37-16(21)非常接近,那麼到底是20、21還是22呢?

根據原則1,我們考慮最簡單情況下的特例。這裡假定整數x的取值範圍上界與下界重合,即x>=16且x<=16,顯然合理的x取值是只有乙個整數,即16。所以當上界與下界重合時,此範圍內滿足條件的整數序列只有乙個元素。

再考慮一般情況,假定下界為l,上界為h。如果滿足條件「上界與下界重合」,即l=h,則h-l=0。根據特例外推的原則,我們可以得出滿足條件的整數序列有h-l+1個元素。故以上的問題中的x的取值個數為37-16+1=22。

造成「欄杆錯誤」的根源正是「h-l+1」中的「+1」。乙個字串中由下標為16到下標為37的字元元素所組成的子串,它的長度是多少呢?稍不留意,就會得到錯誤的結果21。很自然的,我們會想,是否存在一些程式設計技巧,能夠降低這類錯誤發生的可能性呢?

當然,這個技巧不但存在,而且還可以一言以蔽之:用第乙個入界點和第乙個出界點來表示乙個數值範圍。具體而言,前面的例子我們不應該說整數x滿足邊界條件x>=16且x<=37,而是說整數x滿足邊界條件x>=16且x<38。注意,這裡下界是「入界點」,即包括在取值範圍之中;而上界是「出界點」,即不包括在取值範圍之中。這種不對稱也許從數學上而言並不優美,但是它對於程式設計的簡化效果卻足以令人吃驚。

(1)取值範圍的大小就是上界與下界之差。

(2)如果取值範圍為空,那麼上界等於下界

(3)即使取值範圍為空,上界也永遠不可能小於下界。

對於像c這樣的陣列下標從0開始的語言,不對稱邊界給程式設計帶來的便利尤為明顯;這種陣列的上界恰是陣列元素的個數。因此,在c語言中定義乙個擁有10個元素的陣列,那麼0就是陣列下標的第乙個「入界點」,而10就是陣列下標中的第乙個「出界點」。因而我們經常這樣寫

int a[10], i;

for(i=0; i<10; i++)

a[i] = 0;

而不是這樣寫:

int a[10], i;

for(i=0; i<=9; i++)

a[i] = 0;

讓我們做乙個假設,如果c語言的for語句風格類似algol或者pascal語言,那麼就會帶來乙個問題:下面這個語句的含義究竟是什麼?

for(i=0 to 10)

a[i] = 0;

如果10是包括在取值範圍內的「入界點」,那麼i將取11個值,而不是10個值;如果10是不包括在取值範圍內的「出界點」,那麼原來以其他程式語言為背景的程式設計者會大為驚訝。

另一種考慮不對稱邊界的方式是,把上界視作某序列中第乙個被占用的元素,而把下界視作序列中第乙個被釋放的元素。如下圖:

C語言中的邊界計算與不對稱邊界(一)

1 如果乙個陣列有10個元素,那麼這個陣列下標的允許取值範圍是什麼呢?這個問題對於不同的程式語言有著不同的答案。例如,對於fortran,pl i以及snobol4等程式語言,這個陣列的下標取值預設從1開始,而且這些語言也允許程式設計者另外指定陣列下標的起始值。而對於algol和pascal語言,陣...

C語言中sizeof用法中關於邊界對齊的問題

本文主要包括二個部分,第一部分重點介紹在vc中,怎麼樣採用sizeof來求結構的大小,以及容易出現的問題,並給出解決問題的方法,第二部分總結出vc中sizeof的主要用法。1 sizeof應用在結構上的情況 請看下面的結構 struct mystruct 對結構mystruct採用sizeof會出現...

簡單說一下C語言資料型別取值範圍不對稱的原因

首先是,數字在機器中是以補碼形式進行儲存的。了解過原碼 補碼 反碼的應該知道,在正數範圍內,它們三個是一樣的。因此我們討論有符號數的補碼表示。舉例char型別,該型別的取值範圍是 128,127 為什麼tmax比tmin的絕對值小1呢?本來char有8個bits,作為有符號型別,除去最高位,還剩7b...