C 전처리 기는 순환 종속성을 어떻게 처리합니까?
C 전처리 기가 순환 종속성 (#defines)을 처리 하는 방법을 알고 싶습니다 . 이것은 내 프로그램입니다.
#define ONE TWO
#define TWO THREE
#define THREE ONE
int main()
{
int ONE, TWO, THREE;
ONE = 1;
TWO = 2;
THREE = 3;
printf ("ONE, TWO, THREE = %d, %d, %d \n",ONE, TWO, THREE);
}
다음은 전 처리기 출력입니다. 출력이 왜 그런지 알 수 없습니다. 이 경우 전처리 기가 다음 출력을 제공하기 위해 취하는 다양한 단계를 알고 싶습니다.
# 1 "check_macro.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "check_macro.c"
int main()
{
int ONE, TWO, THREE;
ONE = 1;
TWO = 2;
THREE = 3;
printf ("ONE, TWO, THREE = %d, %d, %d \n",ONE, TWO, THREE);
}
이 프로그램을 linux 3.2.0-49-generic-pae에서 실행하고 gcc 버전 4.6.3 (Ubuntu / Linaro 4.6.3-1ubuntu5)에서 컴파일하고 있습니다.
전 처리기 매크로가 확장되는 동안 해당 매크로의 이름은 확장되지 않습니다. 따라서 세 가지 기호는 모두 그 자체로 정의됩니다.
ONE -> TWO -> THREE -> ONE (not expanded because expansion of ONE is in progress)
TWO -> THREE -> ONE -> TWO ( " TWO " )
THREE -> ONE -> TWO -> THREE ( " THREE " )
이 동작은 C 표준의 §6.10.3.4에 의해 설정됩니다 (C11 초안의 섹션 번호, 내가 아는 한 섹션의 단어 및 번호 지정은 C89 이후 변경되지 않음). 매크로 이름이 발견되면 해당 정의로 대체됩니다 ( #
그리고 ##
전 처리기 연산자와 함수형 매크로에 대한 매개 변수가 처리됨). 그런 다음 결과는 더 많은 매크로에 대해 다시 검색됩니다 (나머지 파일의 컨텍스트에서).
2 / 대체 목록을 스캔하는 동안 대체되는 매크로의 이름이 발견되면 (원본 파일의 전처리 토큰의 나머지를 포함하지 않음) 대체되지 않습니다. 또한, 중첩 된 대체가 대체되는 매크로의 이름을 만나면 대체되지 않습니다.
이 절은 재귀 호출로 인해 대체되지 않은 토큰이 사실상 "고정"되어 있다고 말합니다. 절대로 대체되지 않습니다.
… 이러한 대체되지 않은 매크로 이름 전처리 토큰은 매크로 이름 전처리 토큰이 그렇지 않으면 대체되었을 컨텍스트에서 나중에 (재) 검토 되더라도 더 이상 더 이상 대체 할 수 없습니다.
마지막 문장이 언급하는 상황은 실제로 거의 나타나지 않지만 여기에 제가 생각할 수있는 가장 간단한 경우가 있습니다.
#define two one,two
#define a(x) b(x)
#define b(x,y) x,y
a(two)
결과는 one, two
입니다. two
을 (를) one,two
교체 하는 동안 로 확장되고 a
확장 된 항목 two
이 완전히 확장 된 것으로 표시됩니다. 그 후 b(one,two)
확장됩니다. 이것은 더 이상 교체의 맥락에서입니다 two
,하지만 two
의 두 번째 인수 인 b
냉동했다가, 그래서 다시 확장되지 않습니다.
귀하의 질문에 대한 답변은 ISO / IEC 9899 : TC2 섹션 6.10.3.4 "재검색 및 추가 교체", 단락 2 에 의해 답변됩니다 . 앞으로 사양에 대한 질문이있는 경우 사양을 읽어 보시기 바랍니다 .
대체 목록을 스캔하는 동안 대체되는 매크로의 이름이 발견되면 (나머지 소스 파일의 전처리 토큰을 포함하지 않음) 대체되지 않습니다. 또한, 중첩 된 대체가 대체되는 매크로의 이름을 만나면 대체되지 않습니다. 이러한 대체되지 않은 매크로 이름 전처리 토큰은 해당 매크로 이름 전처리 토큰이 그렇지 않으면 대체되었을 컨텍스트에서 나중에 (재) 검토 되더라도 더 이상 대체 할 수 없습니다.
https://gcc.gnu.org/onlinedocs/cpp/Self-Referential-Macros.html#Self-Referential-Macros 는 자체 참조 매크로에 대한 질문에 답합니다.
대답의 핵심은 전처리 기가 자체 참조 매크로를 찾을 때 전혀 확장하지 않는다는 것입니다.
I suspect, the same logic is used to prevent expansion of circularly defined macros. Otherwise, the preprocessor will be in an infinite expansion.
In your example you do the macro processing before defining variables of the same name, so regardless of what the result of the macro processing is, you always print 1, 2, 3
!
Here is an example where the variables are defined first:
#include <stdio.h>
int main()
{
int A = 1, B = 2, C = 3;
#define A B
#define B C
//#define C A
printf("%d\n", A);
printf("%d\n", B);
printf("%d\n", C);
}
This prints 3 3 3
. Somewhat insidiously, un-commenting #define C A
changes the behaviour of the line printf("%d\n", B);
Here's a nice demonstration of the behavior described in rici's and Eric Lippert's answers, i.e. that a macro name is not re-expanded if it is encountered again while already expanding the same macro.
Content of test.c
:
#define ONE 1, TWO
#define TWO 2, THREE
#define THREE 3, ONE
int foo[] = {
ONE,
TWO,
THREE
};
Output of gcc -E test.c
(excluding initial # 1 ...
lines):
int foo[] = {
1, 2, 3, ONE,
2, 3, 1, TWO,
3, 1, 2, THREE
};
(I would post this as a comment, but including substantial code blocks in comments is kind of awkward, so I'm making this a Community Wiki answer instead. If you feel it would be better included as part of an existing answer, feel free to copy it and ask me to delete this CW version.)
'Program Tip' 카테고리의 다른 글
elasticsearch에 "store": "yes"가 필요한 이유는 무엇입니까? (0) | 2020.11.24 |
---|---|
CSS : 부모 높이에 상대적인 이미지 크기를 어떻게 설정할 수 있습니까? (0) | 2020.11.24 |
curl을 사용하여 Chrome을 사용하는 것과 똑같은 GET 요청을 얻는 방법은 무엇입니까? (0) | 2020.11.24 |
운영 체제 또는 아키텍처와 호환되지 않음 : fsevents@1.0.11 (0) | 2020.11.24 |
React / Redux-앱로드 / 초기화에 대한 작업 전달 (0) | 2020.11.24 |