2015-06-27 66 views
2

我看到有人這樣做有數組索引C.這是一個基於C的安全索引技巧嗎?

a = (int *) malloc(sizeof(int)*3) - 1 

從1開始,而不是0有什麼風險呢?

+7

這不過是一個愚蠢的事情。 – haccks

+1

從一開始......可笑。 – HuStmpHrrr

+0

也許可以,只要你有空(a + 1),但我不是一個大粉絲。如果你真的需要基於1的索引(爲什麼?),那麼我寧願看到一個簡單的宏,如#define IND1(x)(x-1)並訪問[IND1(1)]。 – jarmod

回答

10

理論上的風險:只有空指針和指向,到或之後的對象是有效的。其他指針會觸發未定義的使用行爲(如果它們懸掛)或通過指針算術創建它們。

實踐風險:由隨機代碼評論者投訴。

+2

'malloc'必須在這種情況下被施放,因爲它返回一個'void *',你不能在'void *'上做指針運算。 – Cornstalks

+0

@Cornstalks哇。這一個刺傷,但你是完全正確的。 – Quentin

+0

對於standard-ese(儘管來自C++,在這種情況下)在形成一個未定義行爲的無效指針時,請參見[此問題](http://stackoverflow.com/a/15608422/90002) – Novelocrat

3

是否有風險?當然。

malloc通話將保留一些空間,讓您從地址一個,但你設置aA-4。由於A-4可能會存儲一些重要內容,如果您忘記了從1開始索引並且無意中覆蓋了a[0]處的值,那麼您可能會遇到不好的時間。

但更重要的是,爲什麼?它只會讓人們讀到你的代碼而感到困惑。

我會建議對這種褻瀆;)

0

三件事:

首先 - 對我來說,這將是不好的做法,有一個指向真的不屬於你的程序的地址指針。只要你忘記了你創建了一個以1開頭的數組,你就會很快樂地調試你的代碼(相信我你會忘記)。

第二 - 所以你寫這樣的東西。幾個月後,別人來與您的代碼做一些事情,並沒有注意到你放在那裏的那個小-1。他將會有時間調試這段代碼。總之,這是違反總合同。每個人都期望數組或幾乎任何有[]的任何東西都從0開始,以「length - 1」結束。

第三 - 因爲您打破了您製作的數組的一般契約,它不適用於期望數組以0開頭的任何標準庫。每當您決定在數組中使用任何庫時,您都必須記住增加您將作爲參數傳遞的指針。

有了這個,你將不得不做很多記憶和思考和評論(對於使用你的代碼的其他人)。思考和記憶應該留給創造力而不是鍋爐板代碼。

0

只有兩種情況,即在標準允許的指針值指向不是一個有效的對象以外的東西:

  1. 一個null指針值不指向任何東西。可以複製空指針,並可以使用==!=運算符進行比較。在空指針上使用加法,減法或關係運算符;使用解引用操作符會產生未定義行爲,除非在某些情況下,它既不請求實際的解引用操作符,也不請求指針算術[例如, sizeof *p即使在p爲空時也是合法的]。

  2. 對於任何對象,都可能有一個指向該對象的指針或指向該對象的「一個過去」指針;給前者加一會產生後者,而從後者減去一會產生前者。使用==!=運算符指向不同對象的指針和指針可能有時會報告它們相等,即使在使用指向其他對象的指針進行訪問的情況下也是合法的,並且使用「one-past」指針會觸發未定義的行爲。

您的代碼嘗試生成一個指針,該指針不指向任何有效的對象,並且不適合任何描述的行爲類別。請注意,創建一個指向N個元素的「數組」的指針是有可能的和合法的,使得有效下標的範圍從KN到K-1,對於範圍從0到N(包括N個)的任何K(給定一個N個對象的數組,對於總共N + 1個有效指針值,可能產生指向N個對象中的任何一個的指針或指向最後一個對象的指針「one-past」)。然而,第一個對象之前的指針無效。