这是我们以前C++考试中的一道问题。这段代码让我很疯狂,有人能解释一下它是做什么的,尤其是为什么吗?
int arr[3]={10,20,30};
int *arrp = new int;
(*(arr+1)+=3)+=5;
(arrp=&arr[0])++;
std::cout<<*arrp;
这是我们以前C++考试中的一道问题。这段代码让我很疯狂,有人能解释一下它是做什么的,尤其是为什么吗?
int arr[3]={10,20,30};
int *arrp = new int;
(*(arr+1)+=3)+=5;
(arrp=&arr[0])++;
std::cout<<*arrp;
这个语句在没有中间序列点的情况下两次写入对象*(arr+1)
,因此具有未定义行为。
(*(arr+1)+=3)+=5;
该语句在没有中间序列点的情况下两次写入对象arrp
,因此具有未定义行为。
(arrp=&arr[0])++;
这段代码可能导致任何事情发生。
参考:ISO/IEC 14882:2003 5 [expr]/4:“在前一个和下一个序列点之间,标量对象的存储值最多仅通过表达式的评估被修改一次。”
(*(arr+1)+=3)+=5;
arr + 1 - 索引为1的元素
*(arr + 1) - 这个元素的值
(arr + 1) += 3 - 增加3
((arr+1)+=3)+=5 - 增加5;
因此 arr[1] 的值为28
(arrp=&arr[0])++;
arr[0] - 元素0的值
&arr[0] - 元素0的地址
arrp=&arr[0] - 将 arrp 设置为指向元素0的指针
(arrp=&arr[0])++ - 将 arr 设置为指向元素1的指针
结果:28
+= 3
和+= 5
之间没有序列点,它们都作用于同一对象? - CB Bailey这行代码:
(*(arr+1)+=3)+=5;
产生的结果与这个相同(见脚注):
arr[1] += 3;
arr[1] += 5;
(arrp=&arr[0])++;
这段代码将产生与下面脚注中描述的相同结果:
int* arrp = arr+1;
std::cout<<*arrp
输出结果为 28
。
但是这段代码会泄漏内存,因为 int *arrp = new int;
在堆上分配了一个新的 int
,在通过 (arrp=&arr[0])++;
赋值后将丢失。
注:当然,我假设没有奇怪的情况。
编辑: 显然,由于 C++ 标准 5/4 的原因,某些行实际上会导致未定义的行为。所以这真的是一个糟糕的考试问题。
(*(arr+1)+=3)+=5;
与arr[1] += 3; arr[1] += 5;
不相同,因为在第二个语句中引入了一个在第一个语句中不存在的顺序点。 - CB Baileyarr+1
),然后由于括号向外扩展。 - In silico+=
的两个写入不被序列点分开,因此行为是未定义的,除非您有理由说明它不是这样的? - CB Baileyint arr[3]={10,20,30}; // obvious?
int *arrp = new int; // allocated memory for an int
(*(arr+1)+=3)+=5; // (1)
(arrp=&arr[0])++; // (2)
std::cout<<*arrp; // (3)
(1)
*(arr+1)
等同于 arr[1]
,这意味着 *(arr+1)+=3
将会把 arr[1]
增加 3,所以现在 arr[1] == 23
。
(*(arr+1)+=3)+=5
意味着 arr[1]
再增加 5,所以现在它是 28
。
(2)
arrp
将指向 arr
的第一个元素的地址(arr[0]
)。执行完整个语句后,指针 arrp
将被递增,因此它将指向第二个元素。
(3)
打印出 arrp
所指向的内容:即 arr
的第二个元素,也就是 28
。
好的,记住数组可以被解释为指针
int arr[3]={10,20,30};
int *arrp = new int;
arr
数组。(*(arr+1)+=3)+=5;
等同于
*(arr+1)+=3;
*(arr+1)+=5;
*(arr + 1)
指的是数组 arr
的第一个元素,因此 arr[1]
的值增加了八。
(arrp=&arr[0])++;
将第一个数组元素的地址赋给 arrp
,然后将指针递增,现在它指向第二个元素(再次是 arr[1]
)。
通过在 std::cout<<*arrp
中对其进行解引用,您输出了 arr[1]
,它现在的值为 20 + 3 + 5 = 28
。
因此,该代码打印出 28
(并且还创建了一个内存泄漏,因为最初分配给 arrp
的 new int
没有被 delete
)。
我会尝试通过以更简单的方式重写代码来回答你。
int arr[3]={10,20,30};
int *arrp = new int;
(*(arr+1)+=3)+=5;
(arrp=&arr[0])++;
std::cout<<*arrp;
=== 等于 ===
int arr[3]={10,20,30};//create array of 3 elements and assign them
int *arrp = new int;//create an integer pointer and allocate an int to it(useless)
//(*(arr+1)+=3)+=5;
arr[1] = arr[1] + 3;//arr[1] == arr+1 because it is incrementing the arr[0] pointer
arr[1] = arr[1] + 5;
//(arrp=&arr[0])++;
arrp = &arr[0];//point the integer pointer to the first element in arr[]
arrp++;//increment the array pointer, so this really is now pointing to arr[1]
std::cout<<*arrp;//just print out the value, which is arr[1]
我假设你理解指针和基本的C语言。
+=
的结果是一个左值。 - CB Bailey