++c 和 c++ 增量何时应用在这里?
When are the ++c and c++ increments applied exactly here?
只是为了看看我对 ++c
/c++
运算符的工作原理了解多少,我尝试 运行 这些 C 程序:
int c = 5;
c = c - c++;
printf("%d\n", c);
打印 1,我猜逻辑是 ++ 在使用它的代码行之后应用,所以 c
变成 = c - c
即 0,并且在 "next line" 它增加了一个。但这对我来说似乎很奇怪,我想更详细地了解关于运算符优先级应该发生什么。
现在开始:
int c = 5;
c = c - ++c;
printf("%d\n", c);
这个打印 0,我真的不明白为什么。如果右手的值是从左到右解析的,我猜它会读作 c
,即 5,然后是 ++c
,即 6,因为它应该立即应用。或者它是否在整个右手值计算之前计算 ++c
,所以它实际上在做 6 - 6 因为增量还涉及 c
的第一次调用?
c = c - c++;
在 C 中,这是一个非常糟糕的主意(a)。不允许在没有中间序列点的情况下修改和 modify/use 同一对象,并且该减法运算符 不是 序列点。
是个序列点的东西可以在ISO标准的附录C中找到。
(a) 从技术上讲,每个操作的行为(c1
和 c++
的评估,以及对 c
的赋值) 定义明确,但 sequencing 未排序或不确定。在前一种情况下,每个部分的动作可以交错,而在后一种情况下,它们不会交错,但你不知道这两个部分将以什么顺序完成。
但是,标准 C11 6.5/2
也明确指出使用相同变量的排序问题是未定义的行为:
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.
最重要的是,这不是你应该做的事情。
对于 C++(所有版本,说明适用于 C++11 及更高版本):
两者都有 未定义的行为,这意味着它不仅 return 未指定的值,而且会导致整个程序以未定义的方式运行.
原因是表达式内的求值顺序仅针对特定情况指定。计算表达式的顺序不遵循源代码中的顺序,并且与运算符优先级或结合性无关。在大多数情况下,编译器可以自由选择表达式的求值顺序,遵循一些通用规则(例如,运算符的求值 在 其操作数的值计算之后,等等)和一些特定的(例如 &&
和 ||
的左手操作数总是 在 它们的右手操作数之前排序)。
特别是 -
的操作数的计算顺序未指定。据说这两个操作数相对于彼此 unsequenced。
这本身意味着我们不知道 c - [...]
左侧的 c
是否会在增量之前或之后评估为 c
的值。
然而,有一个更严格的规则禁止使用一个标量对象(此处 c
)的值计算,以相对于对同一标量对象的副作用而言未排序的方式。在您的情况下,++c
和 c++
都会对 c
产生副作用,但它们与使用 c - [...]
左侧的值无关。不遵守此规则会导致未定义的行为。
因此您的编译器可以输出它想要的任何内容,您应该避免编写这样的代码。
有关 C++ 的所有计算顺序规则的详细列表,请参阅 cppreference.com。请注意,它们随着不同的 C++ 版本而有所变化,使得越来越多以前未定义或未指定的行为被定义。 None 这些更改适用于您的特定情况。
只是为了看看我对 ++c
/c++
运算符的工作原理了解多少,我尝试 运行 这些 C 程序:
int c = 5;
c = c - c++;
printf("%d\n", c);
打印 1,我猜逻辑是 ++ 在使用它的代码行之后应用,所以 c
变成 = c - c
即 0,并且在 "next line" 它增加了一个。但这对我来说似乎很奇怪,我想更详细地了解关于运算符优先级应该发生什么。
现在开始:
int c = 5;
c = c - ++c;
printf("%d\n", c);
这个打印 0,我真的不明白为什么。如果右手的值是从左到右解析的,我猜它会读作 c
,即 5,然后是 ++c
,即 6,因为它应该立即应用。或者它是否在整个右手值计算之前计算 ++c
,所以它实际上在做 6 - 6 因为增量还涉及 c
的第一次调用?
c = c - c++;
在 C 中,这是一个非常糟糕的主意(a)。不允许在没有中间序列点的情况下修改和 modify/use 同一对象,并且该减法运算符 不是 序列点。
是个序列点的东西可以在ISO标准的附录C中找到。
(a) 从技术上讲,每个操作的行为(c1
和 c++
的评估,以及对 c
的赋值) 定义明确,但 sequencing 未排序或不确定。在前一种情况下,每个部分的动作可以交错,而在后一种情况下,它们不会交错,但你不知道这两个部分将以什么顺序完成。
但是,标准 C11 6.5/2
也明确指出使用相同变量的排序问题是未定义的行为:
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.
最重要的是,这不是你应该做的事情。
对于 C++(所有版本,说明适用于 C++11 及更高版本):
两者都有 未定义的行为,这意味着它不仅 return 未指定的值,而且会导致整个程序以未定义的方式运行.
原因是表达式内的求值顺序仅针对特定情况指定。计算表达式的顺序不遵循源代码中的顺序,并且与运算符优先级或结合性无关。在大多数情况下,编译器可以自由选择表达式的求值顺序,遵循一些通用规则(例如,运算符的求值 在 其操作数的值计算之后,等等)和一些特定的(例如 &&
和 ||
的左手操作数总是 在 它们的右手操作数之前排序)。
特别是 -
的操作数的计算顺序未指定。据说这两个操作数相对于彼此 unsequenced。
这本身意味着我们不知道 c - [...]
左侧的 c
是否会在增量之前或之后评估为 c
的值。
然而,有一个更严格的规则禁止使用一个标量对象(此处 c
)的值计算,以相对于对同一标量对象的副作用而言未排序的方式。在您的情况下,++c
和 c++
都会对 c
产生副作用,但它们与使用 c - [...]
左侧的值无关。不遵守此规则会导致未定义的行为。
因此您的编译器可以输出它想要的任何内容,您应该避免编写这样的代码。
有关 C++ 的所有计算顺序规则的详细列表,请参阅 cppreference.com。请注意,它们随着不同的 C++ 版本而有所变化,使得越来越多以前未定义或未指定的行为被定义。 None 这些更改适用于您的特定情况。