Почему обмен XOR с целыми числами вызывает предупреждение? - PullRequest
3 голосов
/ 27 февраля 2011

Я набрал следующую программу:

#include <stdio.h>

int main(void) {
    int a = 3;
    int b = 42;

    printf("a = %d\nb = %d\n", a, b);

    printf("Exchanging values.\n");
    a ^= b ^= a ^= b;

    printf("a = %d\nb = %d\n", a, b);

    return 0;
}

и все в порядке.Когда я пытаюсь скомпилировать его, я получаю следующее:

$ gcc test.c -o test -Wall -Wextra -ansi -pedantic-errors
test.c: In function ‘main’:
test.c:11: warning: operation on ‘a’ may be undefined

Это довольно стандартный код, не так ли?

Почему это вызывает предупреждение?Насколько я знаю, битовый XOR по умолчанию реализован для int, если вы используете стандартную реализацию C.

Большое спасибо.

Ответы [ 2 ]

13 голосов
/ 27 февраля 2011

Переменная a используется в качестве lvalue дважды в выражении.

Помните, что x ^= y на самом деле является сокращением для x = x ^ y, и это означает, что первый операнд читается,затем пишется.

Если вы берете первую операцию из исходного выражения, это нормально, см .:

   b ^= a ^= b;    // OK
/*    2    1    */

Здесь a используется дважды, а b используетсятри раза.Поскольку оператор присваивания является ассоциативным справа налево, сначала вычисляется a ^= b, переменная b только для чтения, переменная a читается и затем записывается, а результат ( r1 ) равенперешел ко второй операции.Во второй операции b ^= r1, b читается второй раз (давая то же значение, что и ранее), а затем записывается.Обратите внимание, что нет никакого способа интерпретировать по-другому, нет неопределенного поведения.В приведенном выше утверждении a читается только один раз, b читается дважды, но оба чтения возвращают одно и то же значение, а оба a и b записываются только один раз.Это нормально.

Когда вы добавляете третье назначение слева, это становится проблемой:

   a ^= b ^= a ^= b;    // NOT OK
/*    3    2    1    */

Теперь a читается дважды, один раз в операции 1 и один раз воперация 3, а также записано в операции 1 и операции 3. Какое значение должно a возвращать операции 3, исходное значение или значение после обработки операции 1?

Умный программист может подумать, что операция 1полностью выполняется до обработки операции 3, но это не определено стандартом.Так получилось, что он работает с большинством компиляторов.В операции 3 компилятор может очень хорошо вернуть то же значение для a, что и для операции 1, что приведет к неверному результату.Это неопределенное поведение.

9 голосов
/ 27 февраля 2011

a ^= b ^= a ^= b; вызывает Неопределенное поведение . Вы должны использовать это:

a ^= b;
b ^= a;
a ^= b;
...