2009-12-11 91 views
0

編輯:我原本轉錄i++沒有i--UINT作爲指標

現在該代碼,因爲它是,並且在代碼塊編譯和作品的代碼。


爲什麼,如果unsigned int i;代替int i;在下面的代碼片段,使用一個段錯誤的功能結果沒有?

void insertion_sort_int_array(int * const Ints, unsigned int const len) { 
    unsigned int pos; 
    int key; 
    int i; 

    for (pos = 1; pos < len; ++pos) { 
     key = Ints[pos]; 
     for (i = (pos - 1); (i >= 0) && Ints[i] > key; i--) { 
      Ints[i + 1] = Ints[i]; 
     } 
     Ints[i + 1] = key; 
    } 
} 
+1

如果我是無符號的,(i> = 0)的目的是什麼? – 2009-12-11 21:53:31

+0

(i> = 0)的目的是什麼?這總是如此。 – 2009-12-11 21:58:02

回答

2
insertionSort(array A) 
begin 
    for x := 1 to length[A]-1 do 
    begin 
     value := A[x]; 
     i := x - 1; 
     while i >= 0 and A[i] > value do 
     begin 
      A[i + 1] := A[i]; 
      i := i - 1; 
     end; 
     A[i + 1] := value; 
    end; 
end; 

標準插入排序算法和代碼之間的唯一區別是,你增加i代替遞減。那是你的問題。我敢打賭,在你正在編譯和運行的代碼中,你有我 - 而不是內循環中的i ++。這就是爲什麼無符號我有所作爲 - 它不能是負面的,所以內部循環永遠不會結束。您在發佈時是否錯誤地複製了代碼?

編輯:

好了,現在你改變了張貼代碼,這一切是有道理的,對不對?無符號的我會簡單地下溢到INT_MAX,當它減少到0時,這會導致您訪問數組邊界之外的內存。

+0

請注意(根據OP的精神),如果對i使用* unsigned * int,則此代碼將崩潰。當我達到0時,它將設置i:= i-1,它是一個帶符號整數的-1,但是一個非常大的正數*在一個無符號整數中,所以循環永遠不會退出(除了在嘗試在數組邊界之外訪問內存的方式)。 – 2009-12-11 22:18:55

+0

這是用於生成帖子中使用的代碼的psuedocode的實際部分。 – 2009-12-11 22:22:35

1

什麼使i + 1在數組'ints'的範圍內?它看起來像陣列中形成的不良數據會導致你索引到你不應該在的內存區域。

+0

@_ande_turner,但是'ints [i]> key'中的'key'是從您的初始數組中讀取的。這似乎有點危險 – Trent 2009-12-11 21:53:42

2

無論在哪種情況下(可能是段錯誤,可能只是破壞內存),所發佈的代碼都會失敗。

內循環從pos-1開始,在內存中向上掃描,直到滿足一些隨機條件 - 它不檢查是否已經傳遞數組的末尾,所以會快速運行,直到它崩潰或結束條件正好符合它正在破壞的內存(未定義)的內容。

您可能打算在內存中掃描(在循環中使用i--),在這種情況下,它會失敗,因爲循環將達到0.從0減1會給您一個非常大的正數無符號的,所以循環永遠不會結束(i> = 0總是爲真),它將訪問Pluto區域某處的某個內存。

+0

如果在循環的第一次迭代中,ints [i]小於或等於key,那麼它將不做任何事情而退出循環。但是,如果ints [i]大於key,那麼它會將它複製到ints [i + 1],然後將i移到i + 1以進行下一次迭代,所以它只會填充ints [i]後面的內存從循環的第一次迭代開始直到它覆蓋重要的東西(例如,在某些計算機上,它可能會運行到堆棧幀或I/O地址,導致崩潰)或(更可能)從物理內存結束(導致崩潰)。 – 2009-12-11 22:15:29

+0

無論您使用int還是unsigned-int,它都是等待發生的崩潰。 – 2009-12-11 22:15:59

+0

它的初始值是i = pos-1。當我們循環循環時,我每次都會增加(所以它會是pos,然後pos + 1,然後pos + 2 ...)。當「(i> = 0)&& Ints [i]>鍵」時循環結束。也就是說,循環將繼續下去,直到我變爲負數,或者直到數組中的第i個條目大於鍵。由於pos在循環的結束條件中沒有提及,所以pos對循環何時結束沒有影響(除了爲i提供起始值)。看起來您需要詳細瞭解for循環的工作方式。 – 2009-12-11 23:18:33

0

i will [wraparound]會導致訪問超出數組限制。

進口限制和比較UINT_MAX而非以前(i >= 0)修復的問題:

#include <limits.h> 

void insertion_sort_int_array(int * const Integers, unsigned int const N) 
{ 
    unsigned int o; 
    int target; 
    unsigned int i; 

    for (o = 1; o < N; o++) { 
     target = Integers[o]; 
     for (i = (o - 1); (i != UINT_MAX) && (Ints[i] > target); i--) { 
      Integers[i + 1] = Integers[i]; 
     } 
     Integers[i + 1] = key; 
    } 
} 
0

爲什麼,如果unsigned int i;使用 而不是int i;在下面的代碼片段 中,是否在段錯誤中使用函數結果 ?

因爲對於unsigned int ii >= 0始終是真實的,所以你的for循環是不可能終止時,你想要的。

如果您的計數器未簽名,您應該在向後循環(從高到低)時非常小心。