문제
C에는 다음 코드 조각이 있습니다.
int a;
a = 10 + 5 - 3
나는 묻고 싶다:(10+5-3)은 어디에 저장되어 있나요?(내가 아는 한, a
스택에 위치합니다. 어떻습니까? (10+5-3)
?이 rvalue는 어떻게 계산되나요?)
해결책
일반적으로 R- 값은 프로그램 자체 내에 "저장"됩니다.
다시 말해, 컴파일러 자체 (프로그램이 실행되기 전에)는 10 + 5-3 값을 계산합니다 (모두 일정한 즉각적인 값을 기반으로하므로 할 수 있습니다). 어셈블리 코드를 제출 하여이 계산 결과를 할당에 대한 L- 값으로 저장합니다. 컴파일러가 아마도 데이터 세그먼트 원점에 대한 상대 주소로 알고있는 a라는 변수의 경우).
따라서 12 값을 가진 r- 값은 프로그램의 이진 내에서만 발견되며 어셈블리 명령 내에서 발견됩니다. 외모 처럼
mov <some dest, typically DS-relative>, $0C
$ 0C는 "R- 값"입니다.
r- 값이 런타임에만 수행 할 수있는 계산의 결과 인 경우, 기본 C 코드가 다음과 같은 경우 : a = 17 * x; // x 일부 실행 시간 var, r- 값은 프로그램 바이너리 내의 일련의 지침으로 "저장"(또는 오히려 구체화)됩니다. 위의 간단한 "mov dest, imm"과의 차이점은 축합기에 변수 x를로드하는 데 몇 가지 지침이 필요하다는 것입니다. 17을 곱하고 변수 a가있는 주소에 결과를 저장합니다. 컴파일러가 "승인";-) 일부 중간 결과에 스택을 사용하는 것이 가능할 수 있습니다.
a) 완전히 컴파일러 종속
b) 트랜스 앙
c) 그리고 일반적으로 만 포함됩니다 부분 R- 값의
따라서 R- 값은 프로그램의 일부 (데이터가 아닌)에 캡슐화되고 프로그램 바이너리에 저장되지 않은 컴파일 타임 개념이라고 말하는 것이 안전합니다.
Paxdiablo에 대한 응답으로 : 위에서 제시 한 설명은 C 표준이 효과적으로 수행하기 때문에 가능성을 실제로 제한합니다. ~ 아니다 그 성격의 모든 것을 지시하십시오. 절대, 대부분의 r- 값은 결국 적어도 부분적으로 부분적으로 구체화되어 (실행 시간에) 계산 되든 즉시 적절한 값이 제대로 해결 될 수 있도록 물건을 설정하는 일부 지침에 의해 구체화됩니다.
다른 팁
상수는 컴파일 시간에 단순화 될 수 있으므로 문자 그대로 제기 된 질문은 도움이되지 않을 수 있습니다. 그러나 말하는 것과 같은 i - j + k
CPU 아키텍처에 따라 컴파일러가 좋아하는 곳에서 "저장"될 수 있습니다. 컴파일러는 일반적으로 레지스터를 사용하기 위해 최선을 다하려고합니다.
LOAD AX, i
SUB AX, j
ADD AX, k
그러한 표현식을 계산하려면 Accumulator 레지스터 도끼에 "저장"을 계산하려면 일부 메모리 위치에 할당하기 전에 STORE AX, dest
또는 같은. 합리적으로 간단한 표현식을 위해 메모리에 레지스터를 유출하는 데 필요한 반명의 CPU 아키텍처 (예, x86 포함!-)에서 현대 최적화 컴파일러가 필요하다면 놀랍습니다!
이것은 컴파일러 종속입니다. 일반적으로 값 (12)은 컴파일러에 의해 계산됩니다. 그런 다음 코드에 저장되며, 일반적으로 부하/이동 즉시 어셈블리 명령의 일부로 저장됩니다.
그것이 보관하는 곳은 실제로입니다 완전히 컴파일러까지. 표준은이 행동을 지시하지 않습니다.
ㅏ 전형적인 실제로 코드를 컴파일하고 어셈블러 출력을 보면 장소를 볼 수 있습니다.
int main (int argc, char *argv[]) {
int a;
a = 10 + 5 - 3;
return 0;
}
생산 :
.file "qq.c"
.def ___main;
.scl 2;
.type 32;
.endef
.text
.globl _main
.def _main;
.scl 2;
.type 32;
.endef
_main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
andl $-16, %esp
movl $0, %eax
addl $15, %eax
addl $15, %eax
shrl $4, %eax
sall $4, %eax
movl %eax, -8(%ebp)
movl -8(%ebp), %eax
call __alloca
call ___main
movl $12, -4(%ebp) ;*****
movl $0, %eax
leave
ret
관련 비트가 표시됩니다 ;*****
그리고 값이 컴파일러에 의해 생성되고 직접 삽입 된 것을 알 수 있습니다. mov
유형 지침.
표현식이 일정한 값이기 때문에 단순히 간단합니다. 비 스턴트 값 (변수와 같은)을 소개하자마자 코드가 조금 더 복잡해집니다. 그 변수들이 메모리에서 (또는 이미 레지스터에있을 수 있음) 값을 조작해야하기 때문입니다. 실행 시간, 아니다 컴파일 타임.
컴파일러가 값이 무엇인지 계산하는 방법에 관해서는 표현 평가와 관련이 있으며 완전히 다른 질문입니다 :-)
- RHS (오른쪽)의 계산 결과는 "상수 전파"라고하는 단계에서 컴파일러에 의해 계산됩니다.
- 그런 다음 값을
a
다음은 MSVC의 분해입니다.
int a;
a = 10 + 5 - 3;
0041338E mov dword ptr [a],0Ch
귀하의 질문은 잘못된 전제를 기반으로합니다.
의 정의 속성 lvalue C에서는 저장 공간에 위치한다는 것입니다. 저장. 이것이 LValue를 차별화하는 것입니다 rvalue. rvalue입니다 ~ 아니다 어디서나 저장됩니다. 그것이 그것이 rvalue로 만드는 이유입니다. 그것이 저장되면, 그것은 될 것입니다 lvalue 정의에 따라.
"lvalue"와 "rvalue"라는 용어는 표현의 세계를 양분하는 데 사용됩니다.그건, (10+5-3)
rvalue가 되는 표현식입니다(& 연산자를 적용할 수 없기 때문입니다. C++에서는 규칙이 더 복잡합니다).런타임에는 표현식, lvalue 또는 rvalue가 없습니다.특히 어디에도 저장되지 않습니다.
값 12가 어디에 저장되어 있는지 궁금했지만 값 12는 lvalue도 rvalue도 아닙니다. 12
이는 rvalue가 되지만 12
프로그램에는 나타나지 않습니다).