arr[-1]在c++中的奇怪行为
strange behavior of arr[-1] in c++
#include<iostream>
using namespace std;
int main(){
int arr[] = {1,2,3};
printf("outside loop trail 1: arr[-1] = %d n", arr[-1]);
for(int i = 0; i<10; i++){
printf("ninside loop trail i = %d, arr[-1] = %d n", i, arr[-1]);
}
}
问题:
为什么循环内部的输出是序列0,1,2(与循环索引i相同(;但每次执行代码时,循环外的输出都会发生变化?谢谢
后的输出
g++ -o explore explore.cpp && ./explore
外环轨迹1:arr[-1]=537839344
内环轨迹i=0,arr[-1]=0
内环轨迹i=1,arr[-1]=1
内环轨迹i=2,arr[-1]=2
跑步/第二次探索:
外环轨迹1:arr[-1]=1214220016
内环轨迹i=0,arr[-1]=0
内环轨迹i=1,arr[-1]=1
内环轨迹i=2,arr[-1]=2
这实际上包含在标准中。例如,C++17 [expr.add] /4
状态:
将具有整型的表达式添加到指针或从指针中减去时,结果具有指针操作数的类型。如果表达式
P
指向具有n
元素的阵列对象x
的元素x[i]
,则如果0 <= i + j <= n
,则表达式P + J
和J + P
(其中J
具有值j
(指向(可能假设的(元素x[i + j]
;否则,行为是未定义的。
我之所以讨论添加指针和整数,是因为根据C++17 [expr.sub] /1
,array[index]
和*(array + index)
是等价的(这是下标中的sub
,而不是减法(:
表达式
E1[E2]
(根据定义(与*((E1)+(E2))
相同。
现在有很多需要接受的内容,但这基本上意味着添加"指向数组元素的指针"answers"索引"的结果,会给您一个所需的指针,以指向数组中的一个元素或刚好超出最后一个(1(。
由于之前的指针第一个指针(array[-1]
(不符合该要求,因此这是未定义的行为。一旦你做到了,所有的赌注都会落空,实现可以自由地做它喜欢的事情。你可以庆幸它在播放derisive_laughter.ogg
:-(后没有擦除你的硬盘
请注意,负索引本身没有错,下面的代码为您提供了第二个元素(最后的"指针"仍在数组中(:
int array[100];
int *ptrThird = &(array[2]);
int second = ptrThird[-1];
(1(注意,指针可以指向数组之外,前提是您不尝试取消引用它。不幸的是,array[index]
是一个取消引用操作,因此,虽然int array[10]; int *p = &(array[10]);
有效,但int x = array[10];
无效。
这是一个未定义的行为。
一般来说,这样使用数组索引相当于这样做指针数学:
arr[n] -> *(arr+n)
通过使用负索引,可以在与数组数据关联的内存块开始之前引用内存。如果您使用的索引超出了数组的边界,那么正如其他人所指出的,结果是未定义。
expr/1:
后缀表达式后面跟一个方括号中的表达式就是后缀表达式。其中一个表达式应为"T的数组"类型的glvalue或"指向T的指针"类型的prvalue,另一个表达式则应为非范围枚举或整型的prvalue。结果属于"T"类型。类型"T"应为完全定义的对象类型表达式E1[E2](根据定义(与*(((E1(+(E2((相同,只是在数组操作数的情况下,如果该操作数是左值,则结果为左值,否则为x值。在表达E2之前对表达E1进行测序。
expr.add/4:
将具有整型的表达式J添加到指针类型的表达式p中或从中减去时,结果的类型为p。
(4.1(如果p的计算结果为空指针值,而J的计算结果则为0,则结果为零指针值
(4.2(否则,如果P指向具有n个元素的数组对象x的元素x[i],则表达式P+J和J+P(其中J具有值J(在0≤i+J≤n时指向(可能是假设的(元素x[i+J],在0≤i−J≤n的情况下表达式P-J指向(可能假设的(元素x[i-J]。
(4.3(否则,行为未定义
- arr[-1]在c++中的奇怪行为
- 向量 <int> a {N, 0} 和 int arr a[N] = {0} 的时间复杂度有什么区别
- 在C++中用新表达式制作 arr[n][n]
- different between int **arr =new int [ n]; and int a[i][j]?
- arr[n] 是否以 C++ 为单位打印数组的长度?
- 为什么存储在数组中的地址值与其自己的地址相同,它应该指向某个不同的地址(&arr[0])?
- C++:' arr '和' arr[] '有什么区别
- 在 C/C++ 中将数组作为形式参数作为 int arr[] 和 int arr[N] 传递的区别
- 为什么 arr[i++] 与 arr[i]++ 会这样做?
- 这段代码中的arr[s[i]-'a']有什么用,为什么我们用"a"减去所有字符?
- 澄清了 strcpy() 在像这样初始化字符数组时的工作 *Arr.
- 如何理解"vector<int> avector (arr, arr + sizeof(arr) / sizeof(arr[0]) )"?
- 声明数组>> int arr[] 时出错;在C++(虽然在 Java 中有效)?
- 矢量<bool> arr 重置问题
- 根在 arr[0] 的二进制堆有什么好处
- arr[i] = i++ 和 i = i + 1 语句在 C 和 C++ 中的行为
- 访问函数中 const char *arr[] 的元素
- 数组问题:变量周围的堆栈'arr'已损坏
- 失败,dummy_array<int, 6> arr();
- C 将1D动态数组施放到2D数组以使用常规索引(例如ARR [i] [J])