Namespaces
Variants

Binary resource inclusion (since C23)

From cppreference.net

#embed 는 빌드 시 (바이너리) 리소스를 포함하기 위한 전처리기 지시문으로, 여기서 리소스는 번역 환경에서 접근 가능한 데이터 소스로 정의됩니다.

목차

구문

#embed < h-char-sequence > embed-parameter-sequence  (선택 사항) new-line (1)
#embed " q-char-sequence " embed-parameter-sequence  (선택 사항) new-line (2)
#embed pp-tokens new-line (3)
__has_embed ( " q-char-sequence " embed-parameter-sequence  (선택 사항) )
__has_embed ( < h-char-sequence > embed-parameter-sequence  (선택 사항) )
(4)
__has_embed ( string-literal pp-balanced-token-sequence  (선택 사항) )
__has_embed ( < h-pp-tokens > pp-balanced-token-sequence  (선택 사항) )
(5)
1) 고유하게 식별된 h-char-sequence 리소스를 검색하고 해당 리소스의 데이터에 해당하는 정수들의 쉼표로 구분된 목록으로 지시문을 대체합니다.
2) q-char-sequence 로 식별된 리소스를 검색하고 해당 리소스의 데이터에 해당하는 정수 목록으로 지시문을 대체합니다. (1) 으로 폴백(fallback)할 수 있습니다.
3) 만약 (1) (2) 도 매칭되지 않으면, pp-tokens 는 매크로 치환을 거칩니다. 치환 후의 지시문은 (1) 또는 (2) 와 다시 매칭을 시도합니다.
4) 리소스가 임베딩에 사용 가능한지, 비어 있는지 여부 및 전달된 매개변수가 구현에서 지원되는지 확인합니다.
5) 만약 (4) 가 일치하지 않으면, h-pp-tokens pp-balanced-token-sequence 는 매크로 치환을 거칩니다. 치환 후의 지시문은 (4) 와 다시 일치하는지 시도됩니다.
new-line - 개행 문자
h-char-sequence - 하나 이상의 h-char 시퀀스. 다음 중 어느 하나가 나타나면 정의되지 않은 동작을 유발함:
  • 문자 '
  • 문자 "
  • 문자 \
  • 문자 시퀀스 //
  • 문자 시퀀스 /*
h-char - 소스 문자 집합 의 구성원 중 개행 문자와 > 를 제외한 모든 문자
q-char-sequence - 하나 이상의 q-char 시퀀스. 다음 중 어느 하나가 나타나면 정의되지 않은 동작을 유발함:
  • 문자 '
  • 문자 \
  • 문자 시퀀스 //
  • 문자 시퀀스 /*
q-char - 소스 문자 집합 의 구성원 중 개행 문자와 " 를 제외한 모든 문자
pp-tokens - 하나 이상의 전처리 토큰 시퀀스
string-literal - 문자열 리터럴
h-pp-tokens - 전처리 토큰 > 를 제외한 하나 이상의 시퀀스
embed-parameter-sequence - 하나 이상의 pp-parameter 시퀀스. attribute-list 와 달리 이 시퀀스는 쉼표로 구분되지 않음.
pp-parameter - attribute-token ( 속성 참조)이지만 토큰 대신 전처리 토큰으로 구성됨
pp-balanced-token-sequence - balanced-token-sequence ( 속성 참조)이지만 토큰 대신 전처리 토큰으로 구성됨

설명

1) h-char-sequence 로 식별된 리소스를 구현에서 정의된 방식으로 검색합니다.
2) q-char-sequence 로 식별된 리소스를 구현에서 정의하는 방식으로 검색합니다. (1,2) 의 경우, 구현체들은 일반적으로 소스 파일 포함 에 사용되는 구현에서 정의하는 검색 경로와 유사하지만 구별되는 메커니즘을 사용합니다. __has_embed ( __FILE__ ... 구문이 표준의 예제 중 하나에 등장하는데, 이는 적어도 (2) 의 경우 현재 파일이 위치한 디렉터리가 검색될 것으로 예상됨을 시사합니다.
3) 지시문에서 embed 이후의 전처리 토큰들은 일반 텍스트에서와 동일하게 처리됩니다(즉, 매크로 이름으로 현재 정의된 각 식별자는 해당 전처리 토큰들의 대체 목록으로 교체됩니다). 모든 대체 후 생성된 지시문은 앞의 두 가지 형식 중 하나와 일치해야 합니다. < > 전처리 토큰 쌍 사이의 전처리 토큰 시퀀스 또는 한 쌍의 " 문자 사이의 시퀀스가 단일 헤더 이름 전처리 토큰으로 결합되는 방법은 구현에 따라 정의됩니다.
4) h-char-sequence 또는 q-char-sequence 로 식별되는 리소스는 해당 전처리 토큰 시퀀스가 구문 (3) pp-tokens 인 것처럼 검색되며, 추가적인 매크로 확장은 수행되지 않습니다. 이러한 지시문이 #embed 지시문의 구문 요구사항을 충족하지 않을 경우 프로그램은 잘못된 형식입니다. __has_embed 표현식은 리소스 검색이 성공하고, 리소스가 비어 있지 않으며, 모든 매개변수가 지원되는 경우 __STDC_EMBED_FOUND__ 로 평가되고, 리소스가 비어 있으며 모든 매개변수가 지원되는 경우 __STDC_EMBED_EMPTY__ 로 평가되며, 검색이 실패하거나 전달된 매개변수 중 하나가 구현에서 지원되지 않는 경우 __STDC_EMBED_NOT_FOUND__ 로 평가됩니다.
5) 이 형식은 구문 (4) 가 일치하지 않는 경우에만 고려되며, 이 경우 전처리 토큰은 일반 텍스트에서와 동일하게 처리됩니다.

리소스를 찾을 수 없거나 매개변수 중 하나가 구현에서 지원되지 않는 경우, 프로그램은 형식이 잘못되었습니다(ill-formed).

__has_embed #if #elif 표현식에서 확장될 수 있습니다. #ifdef , #ifndef , #elifdef , #elifndef defined 에 의해 정의된 매크로로 취급되지만 다른 곳에서는 사용할 수 없습니다.

리소스는 구현에서 정의된 비트 단위의 크기인 구현 리소스 너비 를 가집니다. 리소스의 리소스 너비 limit 매개변수로 수정되지 않는 한 구현 리소스 너비입니다. 리소스 너비가 0이면 해당 리소스는 비어 있는 것으로 간주됩니다. 임베드 요소 너비 는 구현 정의 매개변수로 수정되지 않는 한 CHAR_BIT 와 동일합니다. 리소스 너비는 임베드 요소 너비로 나누어져야 합니다.

#embed 지시문의 확장은 아래에 설명된 정수 상수 표현식 목록으로부터 형성된 토큰 시퀀스입니다. 목록 내 각 정수 상수 표현식에 대한 토큰 그룹은 이전 정수 상수 표현식에 대한 토큰 그룹과 쉼표로 구분됩니다. 시퀀스는 쉼표로 시작하거나 끝나지 않습니다. 정수 상수 표현식 목록이 비어 있는 경우 토큰 시퀀스도 비어 있습니다. 지시문은 해당 확장으로 대체되며, 특정 embed 매개변수가 존재할 경우 추가 또는 대체 토큰 시퀀스가 함께 적용됩니다.

확장된 시퀀스 내 정수 상수 표현식들의 값은 리소스 데이터의 구현체 정의 매핑에 의해 결정됩니다. 각 정수 상수 표현식의 값은 [ 0 , 2 embed element width ) 범위 내에 있습니다. 만약:

  1. 정수 상수 표현식의 목록은 unsigned char 와 호환되는 타입의 배열을 초기화하는 데 사용되거나, char 가 음수 값을 저장할 수 없는 경우 char 와 호환되는 타입의 배열을 초기화하는 데 사용되며,
  2. embed 요소의 너비는 CHAR_BIT 와 동일합니다.

그렇다면 배열의 초기화된 요소들의 내용은 번역 시점에 리소스의 바이너리 데이터가 배열로 fread 된 것과 같습니다.

구현체는 번역 시 비트 및 바이트 순서와 실행 시 비트 및 바이트 순서를 모두 고려하여 지시문의 리소스 바이너리 데이터를 더 적절하게 표현하도록 권장됩니다. 이는 번역 시 #embed 지시문을 통해 참조된 리소스가 실행 시 수단(예: fread 등)으로 접근된 동일한 리소스일 경우, 연속 저장소에 읽혀진 데이터가 #embed 지시문의 확장 내용으로 초기화된 문자 타입 배열과 비트 단위로 동일하게 비교될 가능성을 최대화합니다.

매개변수

표준은 limit , prefix , suffix 그리고 if_empty 매개변수를 정의합니다. 지시자에 나타나는 다른 모든 매개변수는 구현에서 정의되어야 하며, 그렇지 않으면 프로그램은 형식에 맞지 않습니다. 구현에서 정의된 임베드 매개변수는 지시자의 의미론을 변경할 수 있습니다.

limit

limit( constant-expression ) (1)
__limit__( constant-expression ) (2)

limit 임베드 매개변수는 임베드 매개변수 시퀀스에서 최대 한 번만 나타날 수 있습니다. 이 매개변수는 인수를 가져야 하며, 이 인수는 (전처리기) 상수 표현식 으로 평가되는 음수가 아닌 정수여야 하며 defined 토큰을 포함하지 않아야 합니다. 리소스 너비는 정수 상수 표현식에 임베드 요소 너비를 곱한 값과 구현 리소스 너비 중 더 작은 값으로 설정됩니다.

접미사

suffix( pp-balanced-token-sequence  (선택 사항) ) (1)
__suffix__( pp-balanced-token-sequence  (선택 사항) ) (2)

suffix 임베드 매개변수는 임베드 매개변수 시퀀스에서 최대 한 번만 나타날 수 있습니다. 이는 (비어 있을 수도 있는) 전처리기 인수 절을 가져야 합니다. 리소스가 비어 있지 않으면 매개변수 절의 내용이 지시문의 확장 바로 뒤에 배치됩니다. 그렇지 않으면 아무런 효과가 없습니다.

접두사

prefix( pp-balanced-token-sequence  (선택 사항) ) (1)
__prefix__( pp-balanced-token-sequence  (선택 사항) ) (2)

prefix 임베디드 매개변수는 임베디드 매개변수 시퀀스에서 최대 한 번만 나타날 수 있습니다. 이는 (비어 있을 수도 있는) 전처리기 인수 절을 가져야 합니다. 리소스가 비어 있지 않으면, 매개변수 절의 내용이 지시문의 확장 바로 앞에 배치됩니다. 그렇지 않으면 아무런 효과가 없습니다.

if_empty

if_empty( pp-balanced-token-sequence  (선택적) ) (1)
__if_empty__( pp-balanced-token-sequence  (선택적) ) (2)

if_empty 임베드 매개변수는 임베드 매개변수 시퀀스에서 최대 한 번만 나타날 수 있습니다. 이 매개변수는 (비어 있을 수도 있는) 전처리기 인자 절을 가져야 합니다. 리소스가 비어 있는 경우, 매개변수 절의 내용이 지시문을 대체합니다. 그렇지 않으면 아무런 효과가 없습니다.

예제

#include <stdint.h>
#include <stdio.h>
const uint8_t image_data[] =
{
#embed "image.png"
};
const char message[] =
{
#embed "message.txt" if_empty('M', 'i', 's', 's', 'i', 'n', 'g', '\n')
,'\0' // null terminator
};
void dump(const uint8_t arr[], size_t size)
{
    for (size_t i = 0; i != size; ++i)
        printf("%02X%c", arr[i], (i + 1) % 16 ? ' ' : '\n');
    puts("");
}
int main()
{
    puts("image_data[]:");
    dump(image_data, sizeof image_data);
    puts("message[]:");
    dump((const uint8_t*)message, sizeof message);
}

가능한 출력:

image_data[]:
89 50 4E 47 0D 0A 1A 0A 00 00 00 0D 49 48 44 52
00 00 00 01 00 00 00 01 01 03 00 00 00 25 DB 56
...
message[]:
4D 69 73 73 69 6E 67 0A 00

참고문헌

  • C23 표준 (ISO/IEC 9899:2024):
  • 6.4.7 헤더 이름 (p: 69)
  • 6.10.1 조건부 포함 (p: 165-169)
  • 6.10.2 이진 리소스 포함 (p: 170-177)

참고 항목

C++ documentation for Resource inclusion (since C++26)