2017-10-11 58 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]; 
相关问题