Namespaces
Variants

Storage-class specifiers

From cppreference.net

객체와 함수의 저장 기간(storage duration) 링크(linkage) 를 지정합니다:

  • auto - 자동 지속 기간과 링크 없음
  • register - 자동 지속 기간과 링크 없음; 이 변수의 주소를 취할 수 없음
  • static - 정적 지속 기간과 내부 링크 (블록 범위가 아닌 경우)
  • extern - 정적 지속 기간과 외부 링크 (이미 내부로 선언되지 않은 경우)
  • _Thread_local (C23까지) thread_local (C23부터) - 스레드 저장 기간
(C11부터)

목차

설명

저장 클래스 지정자는 선언 복합 리터럴 표현식에서 (C23부터) 나타납니다. 최대 하나의 지정자만 사용할 수 있습니다 , 단 _Thread_local (C23 이전) thread_local (C23부터) static 또는 extern 과 결합되어 링크를 조정할 수 있습니다 (C11부터) . 저장 클래스 지정자는 선언하는 이름들의 두 가지 독립적인 속성인 저장 기간 링크 을 결정합니다.

1) auto 지정자는 블록 범위에서 선언된 객체(함수 매개변수 목록 제외)에만 허용됩니다. 이는 자동 저장 기간과 링크 없음을 나타내며, 이러한 종류의 선언에 대한 기본값입니다.
2) register 지정자는 블록 범위(함수 매개변수 목록 포함)에서 선언된 객체에만 허용됩니다. 이는 자동 저장 기간과 링크 없음(이러한 종류의 선언의 기본값)을 나타내지만, 추가적으로 가능한 경우 이 변수의 값을 CPU 레지스터에 저장하도록 최적화기에 힌트를 제공합니다. 이 최적화가 수행되든 아니든, register 로 선언된 변수는 주소 연산자 의 인수로 사용할 수 없으며, _Alignas (C23 이전) alignas (C23 이후) 를 사용할 수 없고 (C11 이후) , register 배열은 포인터로 변환할 수 없습니다.
3) static 지정자는 정적 저장 기간 ( _Thread_local 과 결합되지 않는 한) (C11부터) 과 내부 링크age(블록 범위에서 사용되지 않는 한)를 모두 지정합니다. 파일 범위의 함수와 파일 및 블록 범위의 변수와 함께 사용할 수 있지만, 함수 매개변수 목록에서는 사용할 수 없습니다.
4) extern 지정자는 정적 저장 기간 ( _Thread_local (C23까지) thread_local (C23부터) 과 결합되지 않는 한) (C11부터) 과 외부 링크를 지정합니다. 파일 범위와 블록 범위 모두에서 함수 및 객체 선언에 사용할 수 있습니다(함수 매개변수 목록 제외). 이미 내부 링크로 선언된 식별자의 재선언에 extern 이 나타나면 링크는 내부로 유지됩니다. 그렇지 않은 경우(이전 선언이 외부, 무링크였거나 범위 내에 없는 경우) 링크는 외부입니다.
5) _Thread_local (C23까지) thread_local (C23부터) 스레드 저장 기간 을 나타냅니다. 함수 선언과 함께 사용할 수 없습니다. 객체 선언에 사용되는 경우, 동일한 객체의 모든 선언에 존재해야 합니다. 블록 범위 선언에 사용되는 경우, static 또는 extern 과 결합되어 링크age를 결정해야 합니다.
(C11부터)

저장 클래스 지정자가 제공되지 않으면 기본값은 다음과 같습니다:

extern 모든 함수에 대해
extern 파일 범위의 객체에 대해
auto 블록 범위의 객체에 대해

저장 클래스 지정자와 함께 선언된 모든 구조체나 공용체에 대해, 저장 기간(연결은 제외)이 해당 멤버들에 재귀적으로 적용됩니다.

블록 범위의 함수 선언은 extern 을 사용하거나 아무것도 사용하지 않을 수 있습니다. 파일 범위의 함수 선언은 extern 또는 static 을 사용할 수 있습니다.

함수 매개변수는 register 이외의 저장류 지정자를 사용할 수 없습니다. static 이 배열 타입의 함수 매개변수에서 특별한 의미를 가진다는 점에 유의하십시오.

저장 기간

모든 객체 저장 기간 이라는 속성을 가지며, 이는 객체의 수명 을 제한합니다. C 언어에는 네 가지 종류의 저장 기간이 있습니다:

  • automatic 저장 기간. 저장 공간은 객체가 선언된 블록 이 진입될 때 할당되고, 어떤 방식으로든 블록을 빠져나올 때( goto , return , 끝에 도달) 해제됩니다. 한 가지 예외는 VLA 입니다. 이들의 저장 공간은 블록 진입 시가 아닌 선언이 실행될 때 할당되며, 블록을 빠져나올 때가 아닌 선언이 범위를 벗어날 때 해제됩니다 (C99부터) . 블록이 재귀적으로 진입되면, 모든 재귀 수준에 대해 새로운 할당이 수행됩니다. 모든 함수 매개변수와 static 이 아닌 블록 범위 객체는 이 저장 기간을 가지며, 블록 범위에서 사용되는 복합 리터럴 도 마찬가지입니다 (C23까지)
  • static 저장 기간. 저장 기간은 프로그램 전체 실행 기간이며, 객체에 저장된 값은 main 함수 이전에 단 한 번만 초기화됩니다. static 으로 선언된 모든 객체와 내부 또는 외부 링크를 가지는 모든 객체 _Thread_local (C23까지) thread_local (C23부터) 으로 선언되지 않은 객체 (C11부터) 는 이 저장 기간을 가집니다.
  • thread 저장 기간. 저장 기간은 해당 객체가 생성된 스레드의 전체 실행 기간이며, 객체에 저장된 값은 스레드가 시작될 때 초기화됩니다. 각 스레드는 자신만의 고유한 객체를 가집니다. 이 객체에 접근하는 표현식을 실행하는 스레드가 해당 초기화를 실행한 스레드가 아닌 경우, 그 동작은 구현에 따라 정의됩니다. _Thread_local (C23 이전) thread_local (C23 이후) 로 선언된 모든 객체는 이 저장 기간을 가집니다.
(C11 이후)
  • allocated 저장 기간. 저장 공간은 동적 메모리 할당 함수를 사용하여 요청 시 할당 및 해제됩니다.

링키지

링키지(Linkage)는 식별자(변수나 함수)가 다른 스코프에서 참조될 수 있는 능력을 의미합니다. 동일한 식별자를 가진 변수나 함수가 여러 스코프에서 선언되었지만, 모든 스코프에서 참조할 수 없는 경우 여러 개의 변수 인스턴스가 생성됩니다. 다음과 같은 링키지 유형이 인식됩니다:

  • 연결 없음(no linkage) . 해당 변수나 함수는 자신이 속한 스코프(블록 스코프) 내에서만 참조될 수 있습니다. extern 으로 선언되지 않은 모든 블록 스코프 변수와 모든 함수 매개변수, 그리고 함수나 변수가 아닌 모든 식별자는 이 연결을 가집니다.
  • internal linkage . 변수나 함수는 현재 번역 단위의 모든 스코프에서 참조될 수 있습니다. static 또는 constexpr (C23부터) 으로 선언된 모든 파일 스코프 변수는 이 링크를 가지며, static 으로 선언된 모든 파일 스코프 함수도 마찬가지입니다(정적 함수 선언은 파일 스코프에서만 허용됩니다).
  • 외부 연결(external linkage) . 해당 변수나 함수는 전체 프로그램의 다른 모든 번역 단위에서 참조될 수 있습니다. static 으로 선언되지 않은 모든 파일 범위 변수 또는 constexpr (C23부터) 은 이 연결을 가지며, static 으로 선언되지 않은 모든 파일 범위 함수 선언, 모든 블록 범위 함수 선언, 그리고 추가적으로 extern 으로 선언된 모든 변수나 함수는 해당 지점에서 내부 연결을 가진 이전 선언이 보이지 않는 한 이 연결을 가집니다.

동일한 번역 단위에서 동일한 식별자가 내부 링크와 외부 링크를 모두 가지는 경우, 그 동작은 정의되지 않습니다. 이는 잠정적 정의 가 사용될 때 발생할 수 있습니다.

링키지와 라이브러리

외부 연결을 가진 선언들은 일반적으로 헤더 파일에서 제공되며, 이 파일을 #include 하는 모든 번역 단위가 다른 곳에서 정의된 동일한 식별자를 참조할 수 있도록 합니다.

헤더 파일에 내부 링크를 가진 선언이 존재하면, 해당 파일을 포함하는 각 번역 단위마다 별개이고 독립적인 객체가 생성됩니다.

라이브러리 인터페이스, 헤더 파일 "flib.h":

#ifndef FLIB_H
#define FLIB_H
void f(void);              // 외부 링크를 가진 함수 선언
extern int state;          // 외부 링크를 가진 변수 선언
static const int size = 5; // 내부 링크를 가진 읽기 전용 변수 정의
enum { MAX = 10 };         // 상수 정의
inline int sum (int a, int b) { return a + b; } // 인라인 함수 정의
#endif // FLIB_H

라이브러리 구현, 소스 파일 "flib.c":

#include "flib.h"
static void local_f(int s) {} // 내부 링크를 가진 정의 (이 파일에서만 사용됨)
static int local_state;       // 내부 링크를 가진 정의 (이 파일에서만 사용됨)
int state;                       // 외부 링크를 가진 정의 (main.c에서 사용됨)
void f(void) { local_f(state); } // 외부 링크를 가진 정의 (main.c에서 사용됨)

애플리케이션 코드, 소스 파일 "main.c":

#include "flib.h"
int main(void)
{
    int x[MAX] = {size}; // 상수와 읽기 전용 변수를 사용
    state = 7;           // flib.c의 state를 수정
    f();                 // flib.c의 f() 함수 호출
}

키워드

auto , register , static , extern , _Thread_local thread_local

참고 사항

키워드 _Thread_local 은 일반적으로 헤더 파일 <threads.h> 에 정의된 편의 매크로 thread_local 을 통해 사용됩니다.

(C23 이전)

typedef constexpr (C23부터) 지정자는 C 언어 문법에서 형식적으로 저장 클래스 지정자로 분류되지만, 실제 저장 방식을 지정하지는 않습니다.

auto 지정자는 타입 추론을 위해서도 사용됩니다.

(since C23)

파일 범위에서 const 이면서 extern 이 아닌 이름들은 C에서는 외부 링크를 가지지만(모든 파일 범위 선언의 기본값), C++에서는 내부 링크를 가집니다.

예제

#include <stdio.h>
#include <stdlib.h>
// static storage duration
int A;
int main(void)
{
    printf("&A = %p\n", (void*)&A);
    // automatic storage duration
    int A = 1;   // hides global A
    printf("&A = %p\n", (void*)&A);
    // allocated storage duration
    int* ptr_1 = malloc(sizeof(int));   // start allocated storage duration
    printf("address of int in allocated memory = %p\n", (void*)ptr_1);
    free(ptr_1);                        // stop allocated storage duration
}

가능한 출력:

&A = 0x600ae4
&A = 0x7ffefb064f5c
address of int in allocated memory = 0x1f28c30

참고문헌

  • C23 표준 (ISO/IEC 9899:2024):
  • 6.2.2 식별자의 링크 (p: 35-36)
  • 6.2.4 객체의 저장 기간 (p: 36-37)
  • 6.7.1 저장 클래스 지정자 (p: 97-100)
  • C17 표준 (ISO/IEC 9899:2018):
  • 6.2.2 식별자의 링크 (p: 29-30)
  • 6.2.4 객체의 저장 기간 (p: 30)
  • 6.7.1 저장 클래스 지정자 (p: 79)
  • C11 표준 (ISO/IEC 9899:2011):
  • 6.2.2 식별자의 링크 (p: 36-37)
  • 6.2.4 객체의 저장 기간 (p: 38-39)
  • 6.7.1 저장 클래스 지정자 (p: 109-110)
  • C99 표준 (ISO/IEC 9899:1999):
  • 6.2.2 식별자의 링크 (p: 30-31)
  • 6.2.4 객체의 저장 기간 (p: 32)
  • 6.7.1 저장 클래스 지정자 (p: 98-99)
  • C89/C90 표준 (ISO/IEC 9899:1990):
  • 3.1.2.2 식별자의 링크
  • 3.1.2.4 객체의 저장 기간
  • 3.5.1 저장 클래스 지정자

참고 항목

C++ 문서 for Storage class specifiers