HOWTO · C

C의 register 키워드

선언, 주소 제한, 포인터, 범위를 포함하여 C의 register 스토리지 클래스 지정자가 어떻게 동작하는지 알아봅니다.

이 페이지의 내용

이를 지원하는 C 버전에서 register는 전통적으로 객체가 빠른 접근의 이점을 얻을 수 있음을 제안하는 데 사용된 스토리지 클래스 지정자입니다. CPU 레지스터에 저장되는 것을 보장하지도 않고, 프로그램이 더 빨라지는 것을 보장하지도 않습니다. 컴파일러가 객체를 어떻게 구현할지 결정하며, 아래에서 설명하는 규칙은 컴파일러가 대상으로 하는 C 표준에 따라 달라질 수 있습니다.

C의 register 키워드 개요

register 지정자는 오래된 최적화 모델을 반영합니다: 프로그래머는 자주 접근하는 객체를 레지스터 저장 후보로 표시할 수 있었습니다. 현대의 컴파일러는 프로그램과 대상 플랫폼을 바탕으로 최적화 결정을 내리므로, 이 지정자를 추가하는 것은 성능 약속이 아닙니다. 대상 C 버전이 이를 지원하고 그 언어 규칙이 선언에 적합할 때만 사용하세요. 성능이 목표라면 별도로 측정하세요.

CPU에는 제한된 수의 레지스터가 있지만, C는 일반 객체를 매 연산 전에 레지스터에 로드할 것을 요구하지 않습니다. 컴파일러는 프로그램을 변환하고 최적화하면서 값을 레지스터, 메모리 또는 다른 위치에 유지할 수 있습니다. 소스 코드는 특정한 물리적 위치에 의존할 수 없습니다. 선택한 언어 모드에서 컴파일러가 register가 구식이거나 지원되지 않는다고 경고한다면, 해당 컴파일러의 문서와 프로젝트에 구성된 C 버전을 확인하세요.

C에서 register 키워드 사용하기

다음의 완전한 프로그램은 세 개의 지역 객체에 register를 사용하고 그 값들을 출력합니다. 실행 가능한 예제이지만, 그 출력은 여기에 표시하지 않습니다.

#include <stdio.h>

int main(void) {
    register char letter = 'S';
    register double amount = 10.0;
    register int count = 8;

    printf("letter: %c\n", letter);
    printf("amount: %.1f\n", amount);
    printf("count: %d\n", count);
    return 0;
}

선언 구문은 그 외에는 익숙합니다: register를 선언 지정자 사이에, 타입과 식별자보다 앞에 배치합니다. 이 예제는 고정된 값을 사용하므로 선언과 서식화된 출력에 집중할 수 있습니다. 컴파일러가 역사적인 저장 제안을 따를지 여부는 구현상의 결정이며, 프로그램의 정확성은 그 선택에 의존해서는 안 됩니다.

C에서 register 변수의 주소 얻기

register 스토리지 클래스 지정자를 정의하는 C 버전에서는 주소 연산자 &를 register로 선언된 객체에 적용할 수 없습니다. 이 제한은 구현이 우연히 객체의 값을 메모리에 유지하는 경우에도 적용됩니다. 이는 언어 제약이며, 물리적 레지스터에 주소가 있는지에 대한 진술이 아닙니다.

예를 들어, 선언 register int item = 22;는 호환되는 언어 모드에서 유효하지만, int *address = &item;은 제약을 위반합니다. 컴파일러는 제약 위반을 진단해야 하지만, 그 진단의 문구, 심각도, 형식은 구현마다 다릅니다. 다른 컴파일러의 진단을 보장된 출력인 것처럼 복사하지 마세요.

C에서 포인터 변수와 함께 register 사용하기

포인터 객체 자체도 이를 지원하는 C 버전에서는 register를 사용할 수 있습니다. 포인터는 여전히 다른 객체의 주소를 저장할 수 있습니다. 제한은 포인터 객체 자체의 주소를 얻는 데 있습니다. 예를 들어, int value = 15; 뒤에 register int *cursor = &value;를 쓰면 cursor가 value를 가리키고, *cursor는 그 가리키는 정수에 접근합니다.

이 구분은 코드를 읽을 때 유용합니다: &value는 일반 value 객체의 주소를 얻지만, &cursor는 register 포인터 객체의 주소를 얻으려 시도하는 것으로, 같은 제약에 의해 허용되지 않습니다. 이 지정자는 포인터가 무엇을 가리키는지 변경하지 않으며, 어느 객체가 어디에 저장되는지도 보장하지 않습니다. 컴파일러가 선언을 거부하거나 지정자가 지원되지 않는다고 보고하면 대상 언어 모드를 확인하세요.

C에서 register를 다른 스토리지 클래스 지정자와 함께 사용하기

register 자체가 스토리지 클래스 지정자이므로, 같은 선언에서 다른 스토리지 클래스 지정자와 결합할 수 없습니다. 특히, auto register int value;, static register int value;, extern register int value;와 같은 선언은 register를 지원하는 언어 모드에서 유효한 조합이 아닙니다.

컴파일러는 유효하지 않은 조합을 진단하지만, 그 메시지는 고정된 문자열로 표준화되어 있지 않습니다. 유효한 선언을 위해서는 의도한 수명과 연결 규칙에 맞는 하나의 스토리지 클래스 지정자를 선택하세요. 타입(이 예제에서는 int)과 한정자는 선언의 별도 부분이며, 두 개의 스토리지 클래스 지정자를 호환되게 만들지 않습니다.

C에서 register 변수의 범위

이 지정자는 이를 지원하는 C 버전에서 블록 범위 객체와 함수 매개변수를 위한 것이며, 파일 범위 객체에는 허용되지 않습니다. 함수 매개변수는 예를 들어 int total(register int count)와 같이 쓸 수 있습니다. 함수 본문 안에서는 register int count = 22;와 같은 블록 범위 선언도 허용되는 형식입니다. register int count;와 같은 파일 범위 선언은 적용 가능한 제약을 위반하며 진단이 필요합니다.

따라서 “지역 변수"는 불완전한 설명입니다: 허용되는 함수 매개변수의 경우를 가릴 수 있습니다. 범위와 저장 기간은 관련된 개념이지만 서로 바꿔 쓸 수 있는 것은 아닙니다. register 지정자는 객체가 CPU 레지스터에 존재함을 약속하지 않으며, 그 존재가 객체를 일반적인 범위 밖에서 보이게 만들지도 않습니다. 오래된 코드를 유지 보수할 때는 이러한 선언에 의존하기 전에 프로젝트에 선택된 C 버전과 컴파일러 모드를 확인하세요.