如果将地址取一个数组的末尾是合法的,如果数组地址的最后一个元素是0xFFFFFFFF
,我该怎么做呢?
这段代码如何运作:
for (vector<char>::iterator it = vector_.begin(), it != vector_.end(); ++it)
{
}
编辑:
我在这里读到,在提出这个问题之前这是合法的:May I take the address of the one-past-the-end element of an array?
答案 0 :(得分:9)
如果这种情况对于特定体系结构(它可能是也可能不是)是一个问题,那么可以期望编译器和运行时安排分配的数组永远不会在0xFFFFFFFF
结束。如果他们没有做到这一点,并且当一个数组 在那里结束时某些东西就会中断,那么它们将不符合C ++标准。
答案 1 :(得分:3)
访问数组边界是未定义的行为。如果一个恶魔飞出你的鼻子,你不应该感到惊讶(或类似的东西)
实际可能发生的是地址溢出,这可能导致您读取地址为零,从而导致分段错误。
如果你总是在数组范围内,并且你从数组中取出最后一个++it
并将它与_vector.end()
进行比较,那么你实际上并没有访问任何内容而且不应该是个问题。
答案 2 :(得分:1)
答案 3 :(得分:1)
我认为有一个很好的论据可以证明符合条件的C实现不允许数组以(例如)0xFFFFFFFF结束。
让p
成为指向数组的一个元素的指针:如果buffer
被声明为char buffer[BUFFSIZE]
,那么p = buffer+BUFFSIZE
或p = &buffer[BUFFSIZE]
。 (后者的含义相同,其有效性在C99标准文件中明确说明。)
然后我们期望指针比较的普通规则起作用,因为p
的初始化是指针算术的普通位。 (你无法比较标准C中的任意指针,但如果它们都基于单个数组,内存缓冲区或结构,你可以比较它们。)但如果buffer
以0xFFFFFFFF结束,则p
会是0x00000000,我们会遇到p < buffer
!
这将破坏许多现有代码,这些代码假设在相对于数组库完成的有效指针算法中,直观的地址排序属性成立。
答案 4 :(得分:0)
区别在于取消引用该元素并获取其地址。在您的示例中,结尾的元素不会被解除引用,因此它是有效的。虽然在C ++的早期阶段并不是很清楚,但现在已经很清楚了。您传递给下标的值也无关紧要。
答案 5 :(得分:0)
有时你可以对角落案件做的最好的事情是禁止他们。我在NS32032的一些位字段提取指令中看到了这类问题,其中硬件将从字节地址开始加载32位并从该数据中提取。因此,即使映射内存的最后3个字节中的任何位置的单位字段也会失败。解决方案是永远不允许最后4个字节的内存可用于分配。
答案 6 :(得分:0)
相当多的受此影响的体系结构通过为操作系统保留偏移量0xFFFFFFFF
(以及更多)来解决问题。