2017-10-11 24 views
1

(從this deleted question改編。)僅使用指針的數組元素的一個和下一個成員訪問將一個元件

假設我們有一個數組int a[n],我們有在陣列的中間的指針元件(即int *p = &a[y],0 <和n-1)。

如果將p傳遞給我們沒有直接訪問數組的函數,那麼如何在給定數組元素的前後立即訪問這些元素,以便將它們添加到一起?

例如,如果a是在範圍之和可以很容易地這樣得到:

int sum = a[y-1] + a[y+1]; 

但是,在一個函數,其中a不在範圍:

int sum_prev_next(int *p) 
{ 
    ... 
} 

調用這樣的:

sum = sum_prev_next(&a[y]); 

這個函數如何訪問previous和ne xt元素返回總和?

回答

5

假設有問題的指針不指向數組的第一個或最後一個元素,則可以使用指針算術來訪問數組的前一個元素和下一個元素。

int sum_prev_next(int *p) 
{ 
    return *(p-1) + *(p+1); 
} 

或等效:

int sum_prev_next(int *p) 
{ 
    return p[-1] + p[1]; 
} 

負數組下標可以是不尋常的,但是公在這種情況下定義的。這可以用圖來更好地解釋:

 p-1 
     | p p+1 
     | | | 
     v v v 
    ------------------------- 
a | 0 | 1 | 2 | 3 | 4 | 5 | 
    ------------------------- 

如果pa[2],然後p[-1]相同a[1]p[1]相同a[3]

請務必注意,此函數的前提條件是p不指向數組的第一個或最後一個元素。如果是,則訪問p[-1]p[1]將調用undefined behavior,方法是在數組開始之前創建一個指向指針的指針,或者通過取消引用指向數組末尾的指針(創建一個指向末尾的指針爲OK )。

2

根據數組下標的定義(C標準,6.5.2.1數組下標)

2後綴表達式,隨後在方括號表達式[] 是的一個元素的下標一個指定數組對象。下標運算符[]的定義爲E1 [E2]等於 (*((E1)+(E2)))。由於適用於二元運算符 的轉換規則,如果E1是一個數組對象(等同於指向數組對象的初始元素的指針 )且E2是整數,則E1 [E2]指定E2- E1的E1元素(從零開始計數)。

此聲明

int sum = a[y-1] + a[y+1]; 

可以等效改寫等

int sum = *(a + y - 1) + *(a + y + 1); 

,這又可以被改寫等

int sum = *((a + y) - 1) + *((a + y) + 1); 

其中子表達式a + y表示指針p定義像

int *p = &a[y]; 

或(即相同)等

int *p = a + y; 

因爲根據標準轉化(C標準,6.3.2.1左值,數組和功能指示器)

除了它是sizeof運算符的操作數或一元運算符,或者是用於初始化數組的字符串文本,一個 表達式的類型爲'''的數組被轉換爲 表達式,其類型爲指向類型''的指針,該指針指向數組對象的初始 元素並且不是左值。如果數組 對象具有寄存器存儲類,則行爲未定義。

因此,聲明可以被改寫像

int sum = *(p - 1) + *(p + 1); 

現在再從C標準久違的第一次報價,我們得到

int sum = p[-1] + p[1]; 

反之亦然具有上述聲明我們可以改寫它像

int sum = *(p - 1) + *(p + 1); 

考慮到p定義等

int *p = a + y; 

聲明可以被重寫等

int sum = *((a + y) - 1) + *((a + y) + 1); 

int sum = *(a + (y - 1)) + *(a + (y + 1)); 

給出

int sum = a[y-1] + a[y+1]; 
相關問題