문제

이러한 코드 블록이 다른 결과를 산출하는 이유는 무엇입니까?

몇 가지 일반적인 코드:

#define PART1PART2 works
#define STRINGAFY0(s) #s
#define STRINGAFY1(s) STRINGAFY0(s)

사례 1:

#define GLUE(a,b,c) a##b##c  
STRINGAFY1(GLUE(PART1,PART2,*))
//yields
"PART1PART2*"

사례 2:

#define GLUE(a,b) a##b##*
STRINGAFY1(GLUE(PART1,PART2))
//yields
"works*"

사례 3:

#define GLUE(a,b) a##b
STRINGAFY1(GLUE(PART1,PART2*))
//yields
"PART1PART2*"

VS.net 2005 sp1의 MSVC++를 사용하고 있습니다.

편집하다:현재 매크로를 확장할 때 전처리기가 다음과 같이 작동한다고 생각합니다.1 단계:- 본문을 가져 가십시오 - ## 연산자 주변의 공백을 제거하십시오 - 매개 변수의 이름과 일치하는 식별자가 발견되는 경우 문자열을 구문 분석하십시오.-## 연산자 옆에 있는 경우 식별자를 매개변수의 리터럴 값으로 바꿉니다(예:전달된 문자열) -## 연산자 옆에 있지 않은 경우 먼저 매개변수 값에 대해 이 전체 설명 프로세스를 실행한 다음 식별자를 해당 결과로 바꿉니다.(stringafy 단일 '#' 케이스 ATM 무시) -모든 ## 연산자 제거

2 단계:- 결과 문자열을 가져와 매크로에 대해 구문 분석합니다.

이제 저는 세 가지 경우 모두 정확히 동일한 결과 문자열을 생성해야 한다고 생각합니다.

파트1파트2*

따라서 2단계 후에는 다음과 같은 결과가 나와야 합니다.

공장*

그러나 최소한 같은 결과가 나올 것입니다.

도움이 되었습니까?

해결책

사례 1과 2에는 붙여넣고 싶은 유혹이 있으므로 정의된 동작이 없습니다. * 하나의 전처리기 토큰으로 변환됩니다.전처리기의 연관 규칙에 따라 이것은 토큰을 서로 붙이려고 시도합니다. PART1PART2 (또는 그냥 PART2) 그리고 *.귀하의 경우 이는 자동으로 실패할 수 있으며 이는 사물이 정의되지 않은 경우 가능한 결과 중 하나입니다.토큰 PART1PART2 이어서 * 그러면 다시 매크로 확장이 고려되지 않습니다.그런 다음 Stringfication은 여러분이 보는 결과를 생성합니다.

내 gcc는 귀하의 예에서 다르게 동작합니다.

/usr/bin/gcc -O0 -g -std=c89 -pedantic   -E test-prepro.c
test-prepro.c:16:1: error: pasting "PART1PART2" and "*" does not give a valid preprocessing token
"works*"

따라서 귀하의 사례 1을 요약하면 두 가지 문제가 있습니다.

  • 결과가 나오지 않는 두 개의 토큰 붙여넣기 유효한 전처리기 토큰에 있습니다.
  • 평가 순서 ## 운영자

사례 3의 경우 컴파일러가 잘못된 결과를 제공합니다.그래야 한다

  1. 주장을 평가하다STRINGAFY1
  2. 그러려면 확장해야 해 GLUE
  3. GLUE 결과 PART1PART2*
  4. 다시 확장해야 하는 곳
  5. 결과는 works*
  6. 그러면 다음으로 전달됩니다.STRINGAFY1

다른 팁

당신이하는 일을 정확히하고 있습니다.첫 번째 및 두 번째는 기호 이름을 전달하여 새 심볼로 함께 붙여 넣습니다.세 번째는 2 개의 기호를 취하고 그들을 붙여 넣습니다. 그런 다음 * 문자열에 자신을 배치하고 있습니다 (결국 다른 것으로 평가됩니다.)

결과의 질문은 정확히 무엇입니까?무엇을 기대 했는가?나는 그것이 내가 기대할 것으로 기대하는 것처럼 모두 일하는 것처럼 보입니다.

다음 물론 이런 이유로 어쨌든 기호 munging의 어두운 예술을 가지고 노는 이유는 무엇입니까?:)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top