根据N1570(C11草案)6.5.6/8 添加剂操作员:
此外,如果表达式
P指向数组对象的最后一个元素,则表达式(P)+1指向数组对象的最后一个元素之后,如果表达式Q指向一个超过数组对象的最后一个元素,则表达式(Q)-1指向最后一个元素数组对象
子条款6.5.6/9还包含:
此外,如果表达式
P指向要么一个数组对象或一个过去的阵列对象的最后元件,并且表达的元件Q指向相同的数组对象的最后一个元素时,表达((Q)+1)-(P)具有相同的值((Q)-(P))+1和作为-((P)-((Q)+1)),和如果表达式P指向一个超过数组对象的最后一个元素的值,则值为零,即使该表达式(Q)+1未指向数组对象的元素.106)
这证明指针的算术是有效的:
#include <stdio.h>
int main(void)
{
int a[3] = {0, 1, 2};
int *P, *Q;
P = a + 3; // one past the last element
Q = a + 2; // last element
printf("%td\n", ((Q)+1)-(P));
printf("%td\n", ((Q)-(P))+1);
printf("%td\n", -((P)-((Q)+1)));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我希望不允许指向数组越界的元素,其解除引用作为未定义的行为(数组溢出),因此它使它具有潜在的危险性.这有什么理由吗?
指定要作为半闭区间 循环的范围[start, end),特别是对于数组索引,具有一定的令人愉悦的属性,如Dijkstra在他的一个笔记中观察到的.
1)您可以将范围的大小计算为一个简单的函数end - start.特别是,如果范围是根据数组索引指定的,则循环执行的迭代次数将由下式给出end - start.如果范围是[start, end],则迭代次数会end - start + 1非常烦人,不是吗?:)
2)Dijsktra的第二个观察仅适用于(非负)积分指数的情况 - 指定范围为,[start, end)并且(start, end]两者都具有1)中提到的属性.但是,将其指定为(start, end]需要允许索引-1表示包含索引的循环范围0- 您-1只是为了表示范围而允许"非自然"值.该[start, end)公约没有这个问题,因为end是一个非负整数,因此与数组索引打交道时很自然的选择.
Dijsktra对允许的反对与允许-1一个超过容器的最后有效地址有相似之处.但是,由于上述惯例已经使用了很长时间,它很可能说服标准委员会做出这个例外.
| 归档时间: |
|
| 查看次数: |
595 次 |
| 最近记录: |