이 .c 파일 #에는 왜 포함되어 있습니까?
왜 이렇게 거죠?.c
파일#include
자체 그 자체?
vsimple.c
#define USIZE 8
#include "vsimple.c"
#undef USIZE
#define USIZE 16
#include "vsimple.c"
#undef USIZE
#define USIZE 32
#include "vsimple.c"
#undef USIZE
#define USIZE 64
#include "vsimple.c"
#undef USIZE
에 대해 의 서로 할 수 있습니다.USIZE
.
#include
지시문은 실제로 에 동봉되어 있습니다.#ifndef
재귀가 단일 레벨로 제한됩니다.
#ifndef USIZE
// common definitions
...
//
#define VSENC vsenc
#define VSDEC vsdec
#define USIZE 8
#include "vsimple.c"
#undef USIZE
#define USIZE 16
#include "vsimple.c"
#undef USIZE
#define USIZE 32
#include "vsimple.c"
#undef USIZE
#define USIZE 64
#include "vsimple.c"
#undef USIZE
#else // defined(USIZE)
// macro expanded size specific functions using token pasting
...
#define uint_t TEMPLATE3(uint, USIZE, _t)
unsigned char *TEMPLATE2(VSENC, USIZE)(uint_t *__restrict in, size_t n, unsigned char *__restrict out) {
...
}
unsigned char *TEMPLATE2(VSDEC, USIZE)(unsigned char *__restrict ip, size_t n, uint_t *__restrict op) {
...
}
#endif
이 모듈에서 정의되어 있는 기능은 다음과 같습니다.
// vsencNN: compress array with n unsigned (NN bits in[n]) values to the buffer out. Return value = end of compressed output buffer out
unsigned char *vsenc8( unsigned char *__restrict in, size_t n, unsigned char *__restrict out);
unsigned char *vsenc16(unsigned short *__restrict in, size_t n, unsigned char *__restrict out);
unsigned char *vsenc32(unsigned *__restrict in, size_t n, unsigned char *__restrict out);
unsigned char *vsenc64(uint64_t *__restrict in, size_t n, unsigned char *__restrict out);
// vsdecNN: decompress buffer into an array of n unsigned values. Return value = end of compressed input buffer in
unsigned char *vsdec8( unsigned char *__restrict in, size_t n, unsigned char *__restrict out);
unsigned char *vsdec16(unsigned char *__restrict in, size_t n, unsigned short *__restrict out);
unsigned char *vsdec32(unsigned char *__restrict in, size_t n, unsigned *__restrict out);
unsigned char *vsdec64(unsigned char *__restrict in, size_t n, uint64_t *__restrict out);
모두 vsimple.c의 두 가지 함수 정의에서 확장되었습니다.
unsigned char *TEMPLATE2(VSENC, USIZE)(uint_t *__restrict in, size_t n, unsigned char *__restrict out) {
...
}
unsigned char *TEMPLATE2(VSDEC, USIZE)(unsigned char *__restrict ip, size_t n, uint_t *__restrict op) {
...
}
TEMPLATE2
★★★★★★★★★★★★★★★★★」TEMPLATE3
매크로는 conf.h 로 정의되어 있습니다.
#define TEMPLATE2_(_x_, _y_) _x_##_y_
#define TEMPLATE2(_x_, _y_) TEMPLATE2_(_x_,_y_)
#define TEMPLATE3_(_x_,_y_,_z_) _x_##_y_##_z_
#define TEMPLATE3(_x_,_y_,_z_) TEMPLATE3_(_x_, _y_, _z_)
이러한 매크로는 토큰 붙여넣기를 통해 식별자를 만드는 고전적인 프리프로세서 구조입니다. TEMPLATE2
★★★★★★★★★★★★★★★★★」TEMPLATE2_
으로는 ""라고 불립니다.GLUE
★★★★★★★★★★★★★★★★★」XGLUE
.
함수 템플릿은 다음과 같이 시작합니다.
unsigned char *TEMPLATE2(VSENC, USIZE)(uint_t *__restrict in, size_t n, unsigned char *__restrict out) ...
은 첫 됩니다.USIZE
8
만들다
unsigned char *vsenc8(uint8_t *__restrict in, size_t n, unsigned char *__restrict out) ...
포함, '재귀적 포함'USIZE
16
을 다음과같이
unsigned char *vsenc16(uint16_t *__restrict in, size_t n, unsigned char *__restrict out) ...
외에 이 「2」를 정의합니다.vsenc32
★★★★★★★★★★★★★★★★★」vsenc64
.
이러한 전처리된 소스 코드의 사용은 개별 파일에 더 많이 사용됩니다.즉, 모든 공통 정의(특히 매크로)를 포함하는 인스턴스화 부분과 다른 매크로 정의로 여러 번 포함된 코드 및 데이터 템플릿용 개별 파일입니다.
QuickJs의 atom 및 opcode 정의에서 enum, string 및 structures 배열을 생성하는 것이 좋은 예입니다.
@chqrlie 100%에 의해 받아들여진 답변이 무슨 일이 일어나고 있는지를 설명해 줍니다.이것은 단지 보충적인 논평일 뿐이다.
를 는, 2 개의 해, C++ 의 모든 할 수 .vsenc8
,vsenc16
,vsenc32
,vsenc64
★★★★★★★★★★★★★★★★★」vsdec8
,vsdec16
,vsdec32
,vsdec64
그러나 반대로 C는 매우 단순한 언어이며 템플릿을 지원하지 않습니다.같은 파워(더 추악한 패키징)를 갖기 위한 일반적인 방법은 언어의 멍청한 매크로 기능을 사용하여 C 프리프로세서가 동등한 작업을 하도록 하는 것입니다.경험이 있는 대부분의 C프로그래머들은 경력 중에 이런 종류의 구조를 반복적으로 접하고 사용하게 될 것입니다.
이 예제를 이해하기 어려운 것은 구현 파일이 처음에 몇 가지 준비 정의를 가지기 위해 통상적으로 5번 구문 분석되고 다음으로 두 함수의 네 가지 변형이 적용된다는 것입니다. 번째 패스)#ifndef USIZE
프리프로세서 블록)은 필요한 매크로와 비프로세서 블록이 정의되어 재귀적으로 정의됩니다.#include
네 번 다른 방법으로USIZE
값(8
,16
,32
,64
)을 템플릿 값으로 지정합니다.재귀적으로 포함되는 경우, 대응하는 것은#else
프리프로세서 블록은, 다음의 값에 따라서 생성된 2개의 함수의 결과로 해석됩니다.USIZE
패스에 사용되는 매크로 상수.
보다 종래의, 개념적으로 명확하고 즉시 이해하기 쉬운 방법은, 예를 들면, 다른 파일로부터 템플릿 기능을 짜넣는 것입니다.vsimple.impl
:
#define USIZE 8
/* Generate vsenc8(), vsdec8()... */
#include "vsimple.impl"
#undef USIZE
#define USIZE 16
/* Generate vsenc16(), vsdec16()... */
#include "vsimple.impl"
#undef USIZE
#define USIZE 32
/* Generate vsenc32(), vsdec32()... */
#include "vsimple.impl"
#undef USIZE
#define USIZE 64
/* Generate vsenc64(), vsdec64()... */
#include "vsimple.impl"
포함 파일vsimple.c
포함된 파일vsimple.impl
그 후, 무엇을 언제 정의하고 있는지를 보다 명확하게 정리할 수 있습니다.대부분의 C 프로그래머는 구현 패턴을 인식하고 무슨 일이 일어나고 있는지 즉시 알 수 있습니다.
이러한 방식으로 자신을 재귀적이고 반복적으로 포함시키면 난독화된 C 경기 엔트리에 대한 갈채를 받을 수 있지만 미션 크리티컬 생산 코드에 대한 갈채를 받지 않는 호커스 포주술의 느낌을 불러일으킨다.
그것은 재귀다.여기서 재귀는 C 전처리에 루프가 없기 때문에 편리합니다.또한 여러 개의 파일을 확산시키는 것보다 하나의 파일을 사용하여 트릭을 실행하는 것이 바람직합니다.
1~5의 정수를 템플릿 문자열에 보간하여 표준 출력에 출력하는 함수를 작성해야 한다고 가정합니다.를 들어, 1개의 복사 붙여넣기가 되어 있다고 합니다.printf
과 같이 할수 .이치노
void template_print(const char *fmt, int n)
{
if (n == 0) {
template_print(fmt, 1);
template_print(fmt, 2);
template_print(fmt, 3);
template_print(fmt, 4);
template_print(fmt, 5);
} else {
/* imagine there are 30 lines of statements here we don't want
to repeat five times. */
printf(fmt, n);
}
}
은, 「이러다」입니다.template_print("whatever %d\n", 0)
의 n
파라미터를 지정합니다.
의 은, 0 의 .vsimple.c
없이USIZE
정의되어 있습니다.
은 하나의 완결형 함수를 합니다..c
"interface"이 "interface"#include
는 실장입니다.
언급URL : https://stackoverflow.com/questions/71105071/why-does-this-c-file-include-itself
'programing' 카테고리의 다른 글
어레이 Vuex의 뮤트 (0) | 2022.08.18 |
---|---|
다른 문자열 리터럴에 대한 두 문자 포인터의 주소가 동일합니다. (0) | 2022.08.18 |
Java RMI와 RPC의 차이점은 무엇입니까? (0) | 2022.08.18 |
vue: 구문 오류: wait는 예약된 단어입니다. (0) | 2022.08.18 |
Vue.js 컴포넌트를 동적으로 추가 또는 삭제하는 방법(프로그래밍 또는 즉시) (0) | 2022.08.18 |