역사적으로 C 언어에서 lvalue와 rvalue의 구분은 할당 연산자를 적용할 수 있는 표현식을 정의하기 위한 기초로 발생했습니다. Lvalue (left value)는 메모리에서 특정한 위치를 차지하는 객체를 의미하며, 주소를 가져오는 연산자(&)를 적용할 수 있습니다. Rvalue (right value)는 특정 주소가 없는 임시 값을 의미합니다. 이러한 구분은 할당, 함수 인자 전달 및 컴파일러 최적화가 어떻게 작동하는지를 이해하는 데 중요합니다.
문제는 lvalue에 대해서만 허용되는 연산(예: 할당)을 rvalue에 대해 수행하려고 할 때 발생하며, 반대의 경우도 마찬가지입니다. 이는 컴파일 오류를 초래하거나 실행 시점에서 예기치 않은 버그로 이어질 수 있습니다.
해결책은 lvalue와 rvalue 사용 맥락에 대한 명확한 이해입니다. 예:
int x = 5; int y; y = x; // x는 lvalue이자 rvalue이며, y는 lvalue y = x + 1; // x + 1은 rvalue(주소를 가져올 수 없음) // &x는 올바르며, &(x + 1)는 오류
주요 특징:
모든 표현식에서 주소를 가져올 수 있습니까? 예를 들어 (x + y) 표현식의 경우?
아니요, lvalue만 주소를 가지고 있습니다. 예를 들어 (x + y) 표현식은 rvalue입니다.
int z = 3, y = 7; int *p = &(z + y); // 컴파일 오류
상수에 값을 할당하려고 하면(예: 5 = x)?
컴파일 오류가 발생합니다. 리터럴 5는 rvalue이며 lvalue로 사용할 수 없습니다.
5 = x; // 오류: 왼쪽 피연산자는 lvalue가 아닙니다.
함수가 lvalue를 반환할 수 있습니까?
일반 함수는 rvalue를 반환하지만, 참조를 반환하면(예: C++에서) lvalue가 됩니다. C에서는 rvalue만 반환할 수 있습니다.
int foo() { int x = 5; return x; } // rvalue가 반환됩니다.
프로그래머가 임시 결과 표현식(a + b)의 주소를 가져오려고 했습니다:
int *p = &(a + b);
장점:
단점:
프로그래머가 lvalue와 rvalue를 의식적으로 구분합니다. 문법과 의미론에서 허용된 곳에서만 값을 사용합니다:
int x = 7; int *p = &x; // 올바릅니다.
장점:
단점: