C++负数组下标

6

我声明了一个长度为3的整型数组,并想到了下面这段代码:

int a[3];
for(int i = -2; i < 3; ++i){
    a[i] = i; 
    cout<<a[i]<<" ";
}

这是它的输出:
-2 -1 0 1 2 

看起来数组a有5个已分配的空间,而且a正处于这些空间的中间。有任何想法吗?


16
C++没有数组边界检查。无论是向左还是向右索引越界都会导致未定义行为 - Some programmer dude
@SerkanPekçetin提出的问题并没有明确提到负索引,但原则基本上是完全相同的。 - Daniel H
3个回答

40
为了解释负数索引是如何工作的,首先您需要学习(或记住)对于任何数组或指针 a 和索引 i,表达式 a[i] 等于 *(a + i)
这意味着您可以拥有一个指向数组中间元素的指针,并使用正数或负数索引进行简单算术运算。
示例:
int a[3] = { 1, 2, 3 };
int* p = &a[1];  // Make p point to the second element

std::cout << p[-1];  // Prints the first element of a, equal to *(p - 1)
std::cout << p[ 0];  // Prints the second element of a, equal to *p
std::cout << p[ 1];  // Prints the third element of a, equal to *(p + 1)

有点图形化地看,它可以像这样:

+------+------+------+
| a[0] | a[1] | a[2] |
+------+------+------+
^      ^      ^
|      |      |
p-1    p      p+1

现在,当在数组中使用负索引时,就像问题中的a示例一样,它会像这样:

+-----+-------+-------+------+------+------+
| ... | a[-2] | a[-1] | a[0] | a[1] | a[2] |
+-----+-------+-------+------+------+------+

也就是说,在此处使用负索引将会是数组越界,并导致未定义行为


6
这本身是正确的,但它忽略了一个事实,即在问题中使用的“负”索引不在分配的数组内,这种行为是未定义的。 - Tony Delroy
1
@TonyDelroy 我在对问题本身的评论中解决了这个问题。 - Some programmer dude
很遗憾,因为这是一个很好的答案,也正是我来这里寻找的。请在回答前仔细阅读问题。 - kendfss

2

那是你绝对不应该做的事情!C++不检查内置普通数组的边界,因此在技术上,您可以访问超出分配空间(仅为3个int而不是5个)的位置,但最终会产生错误。


1
当我在我的IDE(Visual Studio 2017)上运行时,它抛出了一个异常,说明数组周围的堆栈已经被破坏。我认为发生的事情是分配了3个内存空间,但你强制数组写入了5个空间,这些空间在初始分配之前和之后。从技术上讲,这将起作用,但绝对不推荐这样做。你基本上在内存中覆盖了某些东西,当在大型数组中进行时,这可能会产生不良后果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接