3

我尝试使用 ^= 交换值(我知道最好使用另一个变量来执行此操作),但结果不正确。

#include <stdio.h>

int main() {
    int a = 3, b = 5, *pa = &a, **ppa = &pa, *pb = &b, **ppb = &pb;
    *pa ^= *pb;
    *pb ^= *pa;
    *pa ^= *pb;
    printf("pointer 1: a = %d, b = %d\n", a, b);
    a ^= b ^= a ^= b;
    printf("variables: a = %d, b = %d\n", a, b);
    *pa ^= *pb ^= *pa ^= *pb;
    printf("pointer 2: a = %d, b = %d\n", a, b);
    return 0;
}

结果是

pointer 1: a = 5, b = 3
variables: a = 3, b = 5
pointer 2: a = 0, b = 3

我想知道为什么*pa ^= *pb ^= *pa ^= *pb不能正常工作。谁能告诉我?

4

3 回答 3

7

中的分配之间没有序列点

*pa ^= *pb ^= *pa ^= *pb;

所以行为没有定义。

中的分配之间也没有序列点

a ^= b ^= a ^= b;

所以那条线的行为也是未定义的。如果这发生了,那么你(不)很幸运。

于 2013-11-14T07:43:16.563 回答
3

您需要一个中间序列点。否则,这是未定义的行为。

于 2013-11-14T07:43:27.850 回答
1

在回答你的问题之前,我想先介绍一下:

序列点

序列点是尘埃落定的时间点,到目前为止已经看到的所有副作用都保证是完整的。

该标准规定:

在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的评估修改一次。此外,只能访问先验值以确定要存储的值。

现在,您的问题是,在表达式中

a ^= b ^= a ^= b;  

 *pa ^= *pb ^= *pa ^= *pb;  

只有一个序列点;(在表达式的末尾),并且您在第一个表达式和两个序列点之间的第二个表达式中修改a 了两次(前一个和这些表达式的末尾),这会导致程序的行为undefined*pa;;

进一步阅读:comp.lang.c 常见问题列表 · 问题 3.8

于 2013-11-14T07:56:08.023 回答