728x90

임시변수 없이 swap 구현하기

먼저 이 방법을 알려주는 것은, 이 것이 위험하기 때문에 지양해야 한다는 것을 알리기 위함입니다.

먼저, 그 방법을 소개해보면
#define SWAP(x, y) {(x)^=(y)^=(x)^=(y);}
이와 같은 매크로가 정의되어 있다고 해봅시다.

int main() {
    int x = 10;
    int y = 20;
 
    printf("X = %d, Y = %d", x, y);
 
    x ^= y ^= x ^= y;  //SWAP(x, y);
 
    printf("X = %d, Y = %d", x, y);
 
    return 0;
}
cs

위의 코드와 같이 매크로가 풀리게 될 텐데, 이것을 하나씩 뜯어보면
제일 위의 것부터 x ^= y; -> x = x ^ y;
그러면 x와 y를 2진수로 풀어 봅시다.

x : 00001010 (10진수 : 10)
y : 00010100 (10진수 : 20)

^ 연산자는 xor 이므로 위의 두 수를 xor시키면
x ^ y = 00011110
이 값이 x에 저장되고,

y ^= x; -> y = y ^ x;
x : 00011110
y : 00010100
y ^ x = 00001010
이 값이 y에 저장됩니다.

x ^= y; -> x = x ^ y;
x : 00011110
y : 00001010
x ^ y = 00010100
x에 마지막으로 이 값이 저장됩니다.

최종적으로는,
x : 00010100 (10진수 : 20)
y : 00001010 (10진수 : 10)

이것만 보면 문제가 없어 보이고, 무척 재미있는 트릭 같지만
이것은 매우 주의해서 사용해야 하는 방법입니다.

위의 방법은 부호가 없는 (unsigned) 정수형끼리의 연산에서만 기대하는 것이 좋습니다.
부동 소수점과 같은 경우는 비트 연산을 지원하지 않으며, bit 연산이 가능한 자료형으로 형변환을 해주어야 하는데,
성능을 위해서라면 여기서부터는 껄끄러워지며
(signed) ^ (unsigned) 와 같은 경우 연산은 되지만, 원하지 않은 결과를 초래할 수 있습니다.
또한, unsigned int 끼리의 연산이더라도, SWAP(a, a)와 같이 같은 변수를 swap하는 경우 문제가 발생하게 됩니다.

int main() {
    int a = 20;
    
    SWAP(a, a);
    
    printf("a : %d \n", a);
 
    return 0;
}
cs

실행결과
a : 0

또 종종 지적되는 문제 중 하나가 ^= 트릭의 경우 정수형(무부호 정수형)에만 적용할 수 있는 트릭이므로
-=를 사용해서 부동형까지 확장하는 것인데, 부동형은 실수를 저장하는 것이 아니라 근삿값을 저장하는 것이고
연산과정에서 도입될 수 있는 반올림 오차를 고려한다면 두 값을 "맞바꾼다"고 하기는 힘듭니다.예를 들어 아주 작은 값을 -= 트릭을 이용해서 맞바꾸는 경우 결과로 나오는 값은 심하게 왜곡될 수 있습니다.

728x90
728x90