C 仅使用指向一个元素的指针访问数组元素的上一个和下一个成员
(改编自。)C 仅使用指向一个元素的指针访问数组元素的上一个和下一个成员,c,arrays,pointers,C,Arrays,Pointers,(改编自。) 假设我们有一个数组 int [n] < /代码>,我们有一个指向数组中间元素的指针(即 int *p=和a[y] < /代码> 0<y<n-1)。< /p> 如果p被传递到一个我们无法直接访问数组的函数中,我如何访问给定数组元素前后的元素,以便将它们添加到一起 例如,如果a在范围内,那么可以像这样轻松地获得总和: int sum = a[y-1] + a[y+1]; sum = sum_prev_next(&a[y]); int sum = a[y-1] + a[y+1
假设我们有一个数组<代码> int [n] < /代码>,我们有一个指向数组中间元素的指针(即<代码> int *p=和a[y] < /代码> 0<y<n-1)。< /p> 如果
p
被传递到一个我们无法直接访问数组的函数中,我如何访问给定数组元素前后的元素,以便将它们添加到一起
例如,如果a
在范围内,那么可以像这样轻松地获得总和:
int sum = a[y-1] + a[y+1];
sum = sum_prev_next(&a[y]);
int sum = a[y-1] + a[y+1];
但在a
不在范围内的函数中:
int sum_prev_next(int *p)
{
...
}
这样称呼:
int sum = a[y-1] + a[y+1];
sum = sum_prev_next(&a[y]);
int sum = a[y-1] + a[y+1];
此函数如何访问上一个和下一个元素以返回总和?假设所讨论的指针不指向数组的第一个或最后一个元素,则可以使用指针算法访问数组的上一个和下一个元素
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 |
-------------------------
如果p
指向a[2]
,则p[-1]
与a[1]
相同,p[1]
与a[3]
相同
需要注意的是,此函数的前提条件是
p
不指向数组的第一个或最后一个元素。如果是这样,则访问p[-1]
或p[1]
将通过在数组开始之前创建指向一个的指针或通过取消引用指向数组结束后一个的指针来调用(创建指向结束后一个的指针是可以的).假设所讨论的指针既不指向数组的第一个元素,也不指向数组的最后一个元素,则可以使用指针算法访问数组的上一个和下一个元素
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 |
-------------------------
如果p
指向a[2]
,则p[-1]
与a[1]
相同,p[1]
与a[3]
相同
需要注意的是,此函数的前提条件是
p
不指向数组的第一个或最后一个元素。如果是这样,那么访问p[-1]
或p[1]
将通过在数组开始之前创建指向一个的指针或通过取消引用指向数组结束后一个的指针来调用(创建指向结束后一个的指针是可以的)。根据数组订阅的定义(C标准,6.5.2.1阵列订阅)
2后缀表达式后跟方括号中的表达式[]
数组对象的元素的下标指定
下标运算符[]的定义是E1[E2]与
(*((E1)+(E2))。因为适用于
二进制+运算符,如果E1是数组对象(相当于指针
,E2是一个整数,
E1[E2]指定E1的第E2个元素(从零开始计数)
本声明
int sum = a[y-1] + a[y+1];
可以等效地重写为
int sum = *( a + y - 1 ) + *( a + y + 1 );
int sum = *( ( a + y ) - 1 ) + *( ( a + y ) + 1 );
int sum = *( p - 1 ) + *( p + 1 );
int sum = *( ( a + y ) - 1 ) + *( ( a + y ) + 1 );
反过来也可以像这样重写
int sum = *( a + y - 1 ) + *( a + y + 1 );
int sum = *( ( a + y ) - 1 ) + *( ( a + y ) + 1 );
int sum = *( p - 1 ) + *( p + 1 );
int sum = *( ( a + y ) - 1 ) + *( ( a + y ) + 1 );
其中,子表达式a+y
表示定义如下的指针p
int *p = &a[y];
或者(那是一样的)像
因为根据标准转换(C标准,6.3.2.1左值、数组和函数指示符)
除非它是sizeof运算符或一元数的操作数&
运算符,或是用于初始化数组的字符串文本,
类型为“”的数组“”的表达式转换为
类型为“指向类型的指针”且指向初始值的表达式
数组对象的元素,并且不是左值。如果
对象具有寄存器存储类,行为未定义
所以声明可以像这样重写
int sum = *( a + y - 1 ) + *( a + y + 1 );
int sum = *( ( a + y ) - 1 ) + *( ( a + y ) + 1 );
int sum = *( p - 1 ) + *( p + 1 );
int sum = *( ( a + y ) - 1 ) + *( ( a + y ) + 1 );
现在再次回到我们从C标准中得到的第一个报价
int sum = p[-1] + p[1];
反之亦然有了上述声明,我们可以像
int sum = *( p - 1 ) + *( p + 1 );
考虑到p
like的定义
int *p = a + y;
声明可以重写为
int sum = *( a + y - 1 ) + *( a + y + 1 );
int sum = *( ( a + y ) - 1 ) + *( ( a + y ) + 1 );
int sum = *( p - 1 ) + *( p + 1 );
int sum = *( ( a + y ) - 1 ) + *( ( a + y ) + 1 );
或
那就
根据数组下标的定义(C标准,6.5.2.1数组下标) 2后缀表达式后跟方括号中的表达式[] 数组对象的元素的下标指定 下标运算符[]的定义是E1[E2]与 (*((E1)+(E2))。因为适用于 二进制+运算符,如果E1是数组对象(相当于指针 ,E2是一个整数, E1[E2]指定E1的第E2个元素(从零开始计数) 本声明
int sum = a[y-1] + a[y+1];
可以等效地重写为
int sum = *( a + y - 1 ) + *( a + y + 1 );
int sum = *( ( a + y ) - 1 ) + *( ( a + y ) + 1 );
int sum = *( p - 1 ) + *( p + 1 );
int sum = *( ( a + y ) - 1 ) + *( ( a + y ) + 1 );
反过来也可以像这样重写
int sum = *( a + y - 1 ) + *( a + y + 1 );
int sum = *( ( a + y ) - 1 ) + *( ( a + y ) + 1 );
int sum = *( p - 1 ) + *( p + 1 );
int sum = *( ( a + y ) - 1 ) + *( ( a + y ) + 1 );
其中,子表达式a+y
表示定义如下的指针p
int *p = &a[y];
或者(那是一样的)像
因为根据标准转换(C标准,6.3.2.1左值、数组和函数指示符)
除非它是sizeof运算符或一元数的操作数&
运算符,或是用于初始化数组的字符串文本,
类型为“”的数组“”的表达式转换为
类型为“指向类型的指针”且指向初始值的表达式
数组对象的元素,并且不是左值。如果
对象具有寄存器存储类,行为未定义
所以声明可以像这样重写
int sum = *( a + y - 1 ) + *( a + y + 1 );
int sum = *( ( a + y ) - 1 ) + *( ( a + y ) + 1 );
int sum = *( p - 1 ) + *( p + 1 );
int sum = *( ( a + y ) - 1 ) + *( ( a + y ) + 1 );
现在再次回到我们从C标准中得到的第一个报价
int sum = p[-1] + p[1];
反之亦然有了上述声明,我们可以像
int sum = *( p - 1 ) + *( p + 1 );
考虑到定义