Обмен переменных через XOR - тонкости - C (СИ)

Узнай цену своей работы

Формулировка задачи:

main()
{
    int a=5, b=10;
    a^=b; b^=a; a^=b; printf("%d %d", a, b);
}
main()
{
    int a=5, b=10;
    a^=b^=a^=b; printf("%d %d", a, b);
}
Оба этих кода работают. Википедия говорит, что вторая форма записи - плохо, это undefined behaviour, и может привести к ошибкам. Но у меня это работало, и я успешно пользовался второй записью, как более короткой, в своих

учебных

программах. Однако, как сегодня выяснилось, вторая запись перестает работать, если вынести обмен в функцию:
void swap(int *a, int *b)
{
    *a^=*b; *b^=*a; *a^=*b;
}
 
main()
{
    int a=5, b=10;
    swap(&a, &b); printf("%d %d", a, b);
}
void swap(int *a, int *b)
{
    *a^=*b^=*a^=*b;
}
 
main()
{
    int a=5, b=10;
    swap(&a, &b); printf("%d %d", a, b);
}
Первая форма записи работает, как и раньше, а вот вторая выводит числа 0 и 5 вместо 10 и 5. Хотелось бы разобраться. Компилятор gcc 4.6.3.

Решение задачи: «Обмен переменных через XOR - тонкости»

textual
Листинг программы
main_1.c      **** void swap(int *a, int *b)
   4:main_1.c      **** {
  10                    .loc 1 4 0
  11                    .cfi_startproc
  12 0000 55            push    rbp
  13                    .cfi_def_cfa_offset 16
  14                    .cfi_offset 6, -16
  15 0001 4889E5        mov rbp, rsp
  16                    .cfi_def_cfa_register 6
  17 0004 48897DF8      mov QWORD PTR [rbp-8], rdi
  18 0008 488975F0      mov QWORD PTR [rbp-16], rsi
   5:main_1.c      ****     *a^=*b;
  19                    .loc 1 5 0
  20 000c 488B45F8      mov rax, QWORD PTR [rbp-8]
  21 0010 8B10          mov edx, DWORD PTR [rax]
  22 0012 488B45F0      mov rax, QWORD PTR [rbp-16]
  23 0016 8B00          mov eax, DWORD PTR [rax]
  24 0018 31C2          xor edx, eax
  25 001a 488B45F8      mov rax, QWORD PTR [rbp-8]
  26 001e 8910          mov DWORD PTR [rax], edx
   6:main_1.c      ****     *b^=*a;
  27                    .loc 1 6 0
  28 0020 488B45F0      mov rax, QWORD PTR [rbp-16]
  29 0024 8B10          mov edx, DWORD PTR [rax]
  30 0026 488B45F8      mov rax, QWORD PTR [rbp-8]
  31 002a 8B00          mov eax, DWORD PTR [rax]
  32 002c 31C2          xor edx, eax
  33 002e 488B45F0      mov rax, QWORD PTR [rbp-16]
  34 0032 8910          mov DWORD PTR [rax], edx
   7:main_1.c      ****     *a^=*b;
  35                    .loc 1 7 0
  36 0034 488B45F8      mov rax, QWORD PTR [rbp-8]
  37 0038 8B10          mov edx, DWORD PTR [rax]
  38 003a 488B45F0      mov rax, QWORD PTR [rbp-16]
  39 003e 8B00          mov eax, DWORD PTR [rax]
  40 0040 31C2          xor edx, eax
  41 0042 488B45F8      mov rax, QWORD PTR [rbp-8]
  42 0046 8910          mov DWORD PTR [rax], edx
   8:main_1.c      ****     
   9:main_1.c      **** }

Объяснение кода листинга программы

Код представлен без комментариев, так как они могут быть неактуальными или даже неверными, а также могут затруднять чтение кода. Список переменных и их значений:

  1. a, b - указатели на переменные, которые будут меняться местами
  2. rbp, rsp - регистры, используемые для управления стеком вызовов
  3. edx, eax - временные регистры, используемые в операциях XOR Описание кода:
  4. Сначала функция swap() объявляется как пустая функция с двумя указателями на int в качестве параметров и без возвращаемого значения.
  5. Затем создается стек вызовов с помощью push rbp и mov rbp, rsp.
  6. Далее, QWORD PTR [rbp-8] и QWORD PTR [rbp-16] используются для загрузки значений a и b в регистры edx и eax соответственно.
  7. Затем выполняется операция XOR с использованием xor edx, eax.
  8. После этого значения a и b сохраняются обратно в память с помощью mov DWORD PTR [rax], edx.
  9. Наконец, функция завершается с помощью pop rbp и ret. Поскольку код является функцией, он не имеет собственного состояния или переменных, которые необходимо инициализировать или очистить.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

10   голосов , оценка 4.1 из 5
Похожие ответы