我一直在玩一些代码,看到了一些我不理解的"为什么".

int i = 6;
int j;

int *ptr = &i;
int *ptr1 = &j

j = i++;

//now j == 6 and i == 7. Straightforward.

如果你把算符放在等号的左边呢?

++ptr = ptr1;

相当于

(ptr = ptr + 1) = ptr1; 

鉴于

ptr++ = ptr1;

相当于

ptr = ptr + 1 = ptr1;

后缀运行了一个编译错误,我明白了.赋值运算符左侧有一个常数"ptr+1".很公平.

前缀一个编译并在C++中工作.是的,我知道它很混乱,而且你正在处理未分配的内存,但它可以工作并编译.在C语言中,它不编译,返回与后缀"赋值的左操作数需要左值"相同的错误.无论它是如何编写的,用两个"="运算符或"++ptr"语法展开,都会发生这种情况.

C处理这种赋值的方式和C++处理它的方式有什么不同?

推荐答案

在C和C++中,x++的结果都是右值,所以不能给它赋值.

在C中,++x相当于x += 1(C标准§6.5.3.1/p2;所有C标准cites均符合WG14 N1570).在C++中,++x等于x += 1,如果x不是bool(C++标准)5.3.2[ExPR.PRIM.CCR/P1;所有C++标准引用都是WG21N336).

在C中,赋值表达式的结果是一个右值(C标准§6.5.16/p3):

赋值运算符将值存储在由

因为它不是左值,所以不能分配给它:(C标准§6.5.16/p2-注意这是一个约束)

赋值运算符的左边应该有一个可修改的左值 操作数.

在C++中,赋值表达式的结果是一个LValk(C++标准5.17)[ExPR.ASS] /P1:

赋值运算符(=)和复合赋值运算符 从右到左分组.都需要一个可修改的左值作为其左侧 操作数,并返回引用左操作数的左值.

因此,++ptr = ptr1;是C中可诊断的约束违反,但不违反C++中的任何可诊断规则.

然而,C++11,++ptr = ptr1;之前的版本具有未定义的行为,因为它在两个相邻的序列点之间修改了ptr两次.

在C++11中,++ptr = ptr1的行为得到了很好的定义.如果我们把它改写成

(ptr += 1) = ptr1;

由于C++ 11,C++标准提供了(5.17)[Exp.sAs] /p1.

在所有情况下,赋值都是在值计算之后排序的 的值计算之前,在右操作数和左操作数的 赋值表达式.关于一个 不确定顺序的函数调用,复合函数的操作 作业(job)是单一的判断.

因此,在ptr += 1ptr1的值计算之后,对=执行的赋值进行排序.+=执行的赋值在ptr += 1的值计算之前排序,并且+=所需的所有值计算必须在该赋值之前排序.因此,这里的排序是定义良好的,没有未定义的行为.

C++相关问答推荐

malloc实现:判断正确的分配对齐

Mise()在虚拟内存中做什么?

如何解决C中的严格别名?

在struct中调用函数,但struct在void中 *

如何在Visual Studio代码中关闭此函数名称显示功能?

我编译了一个新的c程序,并收到以下错误

ZED for SDL上的C语言服务器

ESP32在vTaskDelay上崩溃

如何使解释器存储变量

为什么函数是按照定义的顺序执行的,而不是按照从avr-c中的int main()调用的顺序执行的?

Cairo STM32MP1 cairo_Surface_WRITE_TO_PNG始终返回CAROLIO_STATUS_WRITE_ERROR

MacOS下C++的无阻塞键盘阅读

如何将大写/小写土耳其字母相互转换?

如何修复我的qsort()算法?它每次都给出不同的结果

c如何传递对 struct 数组的引用,而不是设置 struct 的副本

GDB 用内容初始化数组

仅使用其内存地址取消引用 C 中的 struct

如何根据当前舍入方向将float转换为int?

将帧从相机 (/dev/video0) 复制到帧缓冲区 (/dev/fb0) 会产生意外结果

从 C 调用 Lua 函数:最小示例导致 LUA_ERRRUN