从堆栈地址形成指针范围是不确定的行为?

Cha*_*l72 9 c c++ pointers undefined-behavior language-lawyer

一些C或C++程序员惊讶地发现即使存储无效指针也是未定义的行为.但是,对于堆或堆栈数组,可以存储一个超过数组末尾的地址,这允许您存储"结束"位置以便在循环中使用.

但是从单个堆栈变量形成指针范围是未定义的行为,如:

char c = 'X';
char* begin = &c;
char* end = begin + 1;

for (; begin != end; ++begin) { /* do something */ }
Run Code Online (Sandbox Code Playgroud)

虽然上面的例子很没用,但是如果某个函数需要一个指针范围,那么这可能很有用,而且你有一个只有一个值来传递它的情况.

这是未定义的行为吗?

Ben*_*igt 14

这是允许的,则该行为被定义并且两者beginend安全地衍生的指针值.

在C++标准第5.7节([expr.add])第4段中:

出于这些运算符的目的,指向非阵列对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,其中对象的类型为其元素类型.

使用C时,可以在C99/N1256标准6.5.6第7节中找到类似的条款.

出于这些运算符的目的,指向不是数组元素的对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,其中对象的类型为其元素类型.


顺便说一下,在3.7.4.3节([basic.stc.dynamic.safety])"安全派生指针"中有一个脚注:

本节不对取消引用未分配的内存的指针施加限制::operator new.这保持了许多C++实现使用二进制库和用其他语言编写的组件的能力.特别是,这适用于C二进制文件,因为取消引用指向分配的内存的指针malloc不受限制.

这表明整个堆栈中的指针算法是实现定义的行为,而不是未定义的行为.