2013-04-09 2 views
12

레지스터 변수의 저장에 관한 요점과 관련하여 명확한 설명을 원합니다. 코드에서 레지스터 변수를 선언 한 경우에만 레지스터에 저장 되나요?C++ 변수를 레지스터에 저장하는 방법

#include<iostream> 
using namespace std; 
int main() 
{ 
register int i=10;// how can we ensure this will store in register only. 
i++; 
cout<<i<<endl; 
return 0; 
} 
+10

C 및 C++은 프로그램이 실행중인 하드웨어에 "레지스터"가 있다고 보증하지 않습니다. 이것은 컴파일러에게 힌트 일뿐입니다. –

+3

왜 신경 썼습니까? – delnan

+4

@StephenCanon C 언어의 힌트가 아닐 뿐이지 만 변수를 선언하면 register가 그 주소를 사용하지 못하게합니다. (레지스터에 실제로 변수를 배치하는 것과 관련하여 힌트가 아닐 수도 있습니다.) –

답변

28

수 없습니다. 변수가 많이 사용되고 있음을 암시하는 것은 컴파일러에게 힌트 일뿐입니다.

저장소 클래스 구체적인 어 register와 객체에 대한 확인 시험 파이 어의 선언은 개체에 대한 액세스가 가능한 한 빨리 제시 다음은 C99의 표현입니다. 그러한 제안이 얼마나 효과적인지는 구현으로 정의됩니다.

register 지정 이렇게 선언 된 변수가 많이 사용됩니다한다는 것을 알 수 있습니다 :

그리고 여기에는 C++ 11 표현입니다. [주의 : 힌트는 무시 될 수 있으며 대부분의 구현에서 변수의 주소가 사용되면 무시됩니다. 이 사용은 더 이상 사용되지 않습니다 (D.2 참조). 사실, register 스토리지 클래스 지정자 C++ 11 (부록 D.2)에있는 사용되지

-end 참고]

스토리지 클래스와 register 키워드의 사용 --specifier (7.1.1)은 더 이상 사용되지 않습니다.

레지스터에 주소가 없으므로 C에서 변수 register의 주소를 가져올 수 없습니다. 이 제한은 C++에서 제거되며 주소를 사용하면 변수가 레지스터에 저장되지 않도록 보장됩니다.

많은 최신 컴파일러는 C++의 register 키워드를 무시합니다 (물론 잘못된 방법으로 사용되지 않는 한). 그들은 register 키워드가 유용 할 때보 다 최적화가 훨씬 간단합니다. 틈새 타겟 플랫폼을위한 컴파일러가 더 심각하게 그것을 처리하기를 기대합니다.

+1

항상 ** 모든 ** 로컬 변수를 'register'로 표시하는 코드를 보게되어 놀랐습니다. –

+3

@PeteBecker 누가 RAM이 필요합니까? 나는 모든 기록원이다! –

+0

당신의 주장은 C++에만 해당됩니다. C는 레지스터 변수에 제한을 부과합니다. –

3

이것은 컴파일러에게 힌트 일뿐입니다. 당신은 을 강제로 변수를 레지스터에 배치 할 수 없습니다. 어쨌든 컴파일러 작성자는 응용 프로그램 프로그래머보다 대상 아키텍처에 대해 훨씬 잘 알고 있으므로 레지스터 할당 결정을 내리는 코드를 작성하는 것이 좋습니다. 즉, register을 사용하면 아무 것도 얻을 수 없습니다.

+0

인수는 C++ 전용입니다. C는 레지스터 변수에 제한을 부과합니다. –

3

일반적으로 불가능합니다. 특히 확률을 높이기위한 특정 조치를 취할 수 있습니다.

적절한 최적화 수준을 사용하십시오.

-O2는 레지스터 변수의 주소를하지 마십시오

register int a,b,c,d,e,f,g,h,i, ... z; // can also produce an error 
// results in _spilling_ a register to stack 
// as the CPU runs out of physical registers 

작은 변수의 수를 유지합니다.

register int a; 
int *b = &a; /* this would be an error in most compilers, but 
       especially in the embedded world the compilers 
       release the restrictions */ 

어떤 컴파일러에서는 제안 할 수

register int a asm ("eax"); // to put a variable to a specific register 
+0

당신의 주장은 C++에만 해당됩니다. C는'register' 변수에 제한을 부과합니다. 또한'asm'에 대한 gcc의 예제는 오도 된 것입니다. gcc의 경우 이것은 "제안"이 아닙니다. 레지스터를 지정하면 해당 레지스터가 있어야하고 *가 사용됩니다. –

1

키워드는 컴파일러가 RAM 2MB의와 시스템에 맞게 한 시간의 남은 (A와 18 개 단자 사이에 공유되는 "등록" 사용자가 각각 로그인). 또는 128-256KB RAM의 PC/가정용 컴퓨터. 이 시점에서 컴파일러는 레지스터를 가장 효과적으로 사용하기 위해 어떤 변수에 어떤 레지스터를 사용할지를 결정하기 위해 큰 함수를 실행하지 못했습니다. 따라서 프로그래머가 register으로 "힌트"를 주면 컴파일러는이를 가능한 한 레지스터에 넣습니다.

현대 컴파일러는 2MB의 RAM에 여러 번 적합하지 않지만 변수를 레지스터에 할당하는 것이 훨씬 더 똑똑합니다. 주어진 예에서, 나는 컴파일러가 그것을 레지스터에 넣지 않을 것이라는 것을 아주 쉽게 알 수있다. 분명히 레지스터의 수가 제한되어 있고 코드가 충분히 복잡한 경우 일부 변수는 레지스터에 맞지 않습니다. 그러나 그러한 간단한 예제의 경우, 현대 컴파일러는 i을 레지스터로 만들 것이고 ostream& ostream::operator<<(ostream& os, int x) 안에 어딘가까지 메모리를 만지지 않을 것입니다.

+0

하하, 2MB의 단자 18 개. 내 잔디에서 내리십시오 :-) [CP-67은 60 명의 사용자를 지원했습니다] (http://www.leeandmelindavarian.com/Melinda/25paper.pdf) [절반에] (http://bitsavers.trailing-edge.com /pdf/ibm/360/funcChar/GA27-2719-2_360-67_funcChar.pdf). – jthill

+0

그래, 우리 학교는 RSTS-E를 운영하는 2MB PDP-11을 공유했는데 내 학교에는 8 개의 단말기와 프린터가 있었고 다음 학교에는 8 + 1 개의 프린터가 있었고 그 다음에 본 학교에는 각 방에 16 개의 터미널이있는 2 개의 방이있었습니다 (플러스 몇 가지 다른 장소에 흩어져 몇 무작위 터미널). 그리고 거기에는 C 컴파일러가 있었지만, 우리 대부분은 그 당시의 현대적인 언어 인 Pascal을 사용했습니다. –

5

register 키워드는 C 및 C++에서 다른 의미를 갖습니다. C++에서는 실제로 중복되어 있으며 요즘에는 더 이상 사용되지 않는 것처럼 보입니다.

C에서는 다릅니다. 먼저 키워드의 이름을 그대로 사용하지 마십시오. 최신 CPU의 "하드웨어 레지스터"와 항상 관련이있는 것은 아닙니다. register 변수에 부과 된 제한 사항은 주소를 사용할 수 없다는 것이므로 & 작업은 허용되지 않습니다. 이렇게하면 최적화를 위해 변수를 표시하고 주소를 취하려고하면 컴파일러에서 소리를 지르도록 할 수 있습니다. 특히 register 변수는 const으로 한정 될 수 없으므로 별칭을 지정할 수 없으므로 최적화를위한 좋은 후보가됩니다.

C에서와 같이 register을 사용하면 변수의 주소를 가져 오는 모든 장소를 체계적으로 생각하게됩니다. 이것은 아마도 객체와 객체에 대한 참조에 크게 의존하는 C++에서하고 싶지 않을 것입니다. 이것은 C++이 register 변수의이 속성을 C에서 복사하지 않았기 때문일 수도 있습니다.

+0

나는 두 번째 단락의 첫 번째 문장에서 "verbose"대신 "문자 그대로"(또는 "축 어적") 것을 의미한다고 생각합니다. – Jeff

0

인서트 어셈블리를 사용하는 유일한 방법은 레지스터를 사용하는 것입니다. 그러나 이렇게해도 컴파일러가 값을 인라인 어셈블리 블록의 외부에 저장하지 않는다고 보장 할 수는 없습니다. 그리고 물론, OS는 CPU를 다른 프로세스에 제공하기 위해 모든 레지스터를 메모리에 저장하여 언제든지 프로그램을 중단하도록 결정할 수 있습니다.

그래서 모든 인터럽트가 비활성화 된 상태에서 커널 내에 어셈블러 코드를 작성하지 않으면 변수가 메모리에 절대 절대로 도달하지 못하게하는 방법이 전혀 없습니다.

물론 안전에 관심이있는 경우에만 해당됩니다. 성능 측면에서 보면 보통 -O3으로 컴파일하는 것으로 충분합니다. 컴파일러는 일반적으로 레지스터에서 보유 할 변수를 결정할 때 꽤 좋은 작업을합니다. 어쨌든 변수를 레지스터에 저장하는 것은 성능 튜닝의 작은 측면 중 하나 일 뿐이지 만 훨씬 더 중요한 측면은 불필요하거나 값 비싼 작업이 내부 루프에서 수행되지 않도록하는 것입니다.

0

을 레지스터에 저장하려면 C++에서 volatile register int i = 10을 사용할 수 있습니다. volatile 키워드를 사용하면 컴파일러에서 변수 i을 최적화 할 수 없습니다.

1

일반적으로 CPP 컴파일러 (g ++)는 코드를 상당히 최적화합니다. 따라서 레지스터 변수를 선언 할 때 컴파일러가 해당 값을 레지스터에 직접 저장할 필요는 없습니다. (즉) 'register int x'코드가 컴파일러에서 해당 int를 레지스터에 직접 저장하지 못할 수 있습니다. 그러나 컴파일러에게 그렇게하도록 강제 할 수 있다면 성공할 수 있습니다.

예를 들어 다음 코드를 사용하면 컴파일러가 원하는 것을 수행 할 수 있습니다. 다음 코드 조각을 컴파일하면 오류가 발생하여 int가 실제로 레지스터에 직접 저장되고 있음을 나타낼 수 있습니다.

int main() { 
    volatile register int x asm ("eax"); 
    int y = *(&x); 
    return 0; 
} 

이 경우 g ++ 컴파일러에서 다음과 같은 오류가 발생합니다.

[[email protected] cpp]$ g++ register_vars.cpp 
register_vars.cpp: In function ‘int main()’: 
register_vars.cpp:3: error: address of explicit register variable ‘x’ requested 

라인 '휘발성 레지스터 INT의 X의 ASM ("EAX")는'EAX '의 정수 X를 저장, 컴파일러를 지시 레지스터 및 최적화를하지 않도록하고있다. 이렇게하면 값이 레지스터에 직접 저장됩니다. 그래서 변수의 주소에 액세스하면 오류가 발생합니다.

또는 C 컴파일러 (gcc)는 다음 코드 자체에서 오류가 발생할 수 있습니다.

int main() { 
    register int a=10; 
    int c = *(&a); 
    return 0; 
} 

나를 위해 gcc 컴파일러는이 경우 다음과 같은 오류가 발생합니다.

[[email protected] cpp]$ gcc register.c 
register.c: In function ‘main’: 
register.c:5: error: address of register variable ‘a’ requested 
+0

이'asm ("eax") 구문은 내가 찾고있는 구문과 정확히 일치한다. 실제로 질문에 답변 해 주셔서 감사합니다. – portforwardpodcast

관련 문제