Computer >> 컴퓨터 >  >> 프로그래밍 >> C 프로그래밍

C/C++ R-값 표현식의 비밀: ~x 연산 후에도 값이 변하지 않는 이유

이번 글에서는 흥미로운 C/C++ 퍼즐 하나를 살펴보겠습니다. 아래와 같은 프로그램이 주어졌을 때, 출력 결과가 무엇이고 그 이유는 무엇인지 맞혀보시기 바랍니다.

예제 코드

#include<iostream>
using namespace std;
int main() {
    int x = 0xab;
    ~x;
    cout << hex << x;
}

과연 출력 결과는 무엇일까요? ~x는 비트 보수(complement) 연산을 수행하므로, 16진수 형태로 보수된 결과가 출력될 것이라고 생각하기 쉽습니다.

하지만 실제 실행 결과는 다음과 같습니다.

출력 결과

ab

값이 전혀 변하지 않았습니다. 도대체 왜 그런 걸까요?

R-값(R-value)과 L-값(L-value)의 차이

핵심은 ~x라는 표현식이 R-값 표현식이라는 점입니다. ~x는 x의 비트를 반전한 새로운 임시 값을 생성할 뿐, 그 결과를 어떤 변수에도 저장하지 않습니다. 계산된 값은 임시 객체에 존재하다가 해당 문장이 끝나면 곧바로 사라지기 때문에, 원래 변수 x에는 아무런 영향을 주지 못합니다.

C/C++에서 연산의 결과를 실제로 유지하려면 반드시 대입 연산자(=)를 사용해 L-값에 저장해야 합니다. 즉, 다음과 같이 코드를 수정해야 합니다.

수정된 예제 코드

#include<iostream>
using namespace std;
int main() {
    int x = 0xab;
    x = ~x;
    cout << hex << x;
}

출력 결과

ffffff54

이번에는 x = ~x;를 통해 보수 연산의 결과가 다시 x에 대입되었기 때문에, 32비트 int 기준으로 0xab(000000ab)의 모든 비트를 반전한 ffffff54가 정상적으로 출력됩니다.

정리

이 예제를 통해 배울 수 있는 핵심은 다음과 같습니다.

  • R-값 표현식은 계산 결과를 생성하지만, 별도의 변수에 저장하지 않으면 곧바로 사라집니다.
  • 연산 결과를 유지하려면 L-값에 대입하는 과정이 반드시 필요합니다.
  • 컴파일러는 이러한 코드를 오류로 판단하지 않으므로, 개발자가 스스로 주의해야 하며 최신 컴파일러에서는 불필요한 문장에 대해 경고를 표시할 수 있습니다.