C语言前缀后缀问题

标签 c prefix postfix-notation

<分区>

我用c写了下面的代码

int x = 8;
x -= --x - x--;
printf("%d", x);

它正在打印 6 但根据我的逻辑语句应该转换为(从右到左执行)

x = 6-6-8; 

所以答案应该是-8。

谁能说说这里发生了什么?

最佳答案

这是未定义的行为。 C99 标准 §6.5 ¶2 说

Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be read only to determine the value to be stored.

x -= --x - x--;

// equivalent to
x = x - --x - x--;

// postfix decrement has higher precedence than
// prefix decrement. Both have higher precedence than
// subtraction operator. Therefore the above statement is
// equivalent to
x = x - (--x) - (x--);

// the subtraction associates from left to right 
// therefore the above statement is parsed as
x = (x - (--x)) - (x--);

现在,这里要注意的重要一点是 - 运算符的操作数的计算相对于彼此是无序的。这意味着它不是固定的子表达式 (x - (--x))(x--) 将首先被评估。

引自这篇优秀文章Order of evaluation来自 cppreference.com -

There is no concept of left-to-right or right-to-left evaluation in C, which is not to be confused with left-to-right and right-to-left associativity of operators: the expression a + b + c is parsed as (a + b) + c due to left-to-right associativity of operator+, but the subexpression c may be evaluated first (or last, or at the same time as a or b) at run time.

第二个要注意的是在上面的语句中,由于表达式 --x 的副作用,x 的值被修改了两次x--。这两个表达式的求值之间没有序列点,因此无法保证副作用何时发生。因此,引用标准中的上述部分,它是未定义的行为。

结合上述两点,表达式可以计算出多个值。

int x = 8;
x = (x - (--x)) - (x--);
//  (a)   (b)      (c)   name of the sub expressions

// assume (c) is evaluated first and side effect
// takes place immediately. Then (b) is evaluated and
// side effect takes place immediately

x = (6 - (6)) - (8);   // -8

// assume (a) is evaluated first, then (b)
// however the side effect of (b) does not take
// place before (c) gets evaluated          

x = (8 - (7)) - (7);   // -6      

这只是两个示例,用于说明 x 在语句执行后可能具有的不同值。这不应被理解为 x 将始终具有所有可能值中的一个值。该标准说它是未定义的行为,这意味着该行为是不可预测的。该标准对处理此类情况的实现没有强加要求。未定义的行为意味着任何事情都可能发生,从你的 Nose 飞出的守护进程到你的硬盘被格式化。您应该始终避免编写调用未定义行为的代码。有关更多详细信息,请阅读此 - Undefined Behavior and Sequence Points .

关于C语言前缀后缀问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23026294/

相关文章:

html - C/HTML - 从 HTML 表单打印用户名和密码

c++ - 对于 malloc() 失败是否有等效的 set_new_handler()?

java - 如何在 Infix 到 Postfix 后将整数分组在一起

sql - AST 与后缀算法

python - 如何在python中删除路径前缀?

java - Java Println 如何评估特殊符号和算术运算?

c - scanf: "%[^\n]"跳过第二个输入但 "%[^\n]"没有。为什么?

c - glFlush() 不显示任何内容

git-svn - 如何在Git-Svn存储库中更改前缀映射?

java - javafx中的preferred是什么意思