이 .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) ...
은 첫 됩니다.USIZE8만들다
unsigned char *vsenc8(uint8_t *__restrict in, size_t n, unsigned char *__restrict out) ...
포함, '재귀적 포함'USIZE16을 다음과같이
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 |