이중 스트링 화 트릭은 정확히 어떻게 작동합니까?


84

적어도 일부 C 전처리기를 사용하면 하나의 함수와 유사한 매크로를 통해이를 문자열 화하는 다른 매크로로 전달하여 매크로의 이름이 아닌 값을 문자열화할 수 있습니다.

#define STR1(x) #x
#define STR2(x) STR1(x)
#define THE_ANSWER 42
#define THE_ANSWER_STR STR2(THE_ANSWER) /* "42" */

여기에 사용 사례의 예가 있습니다 .

이것은 적어도 GCC와 Clang (둘 다 -std=c99)에서 작동하지만 C 표준 용어로 어떻게 작동 하는지 잘 모르겠습니다 .

이 동작이 C99에 의해 보장됩니까?
그렇다면 C99는 어떻게 보장합니까?
그렇지 않은 경우 어떤 시점에서 동작이 C 정의에서 GCC 정의로 이동합니까?


1
"적어도 일부"라고 말하면 작동하지 않는 곳을 본 적이 있습니까? 공급 업체에 버그 보고서를 기꺼이 작성하겠습니다.
Jens

@Jens : 아니요. 나는하지 않았다. 내가 사용한 모든 컴파일러 (즉, GCC 및 Clang)는이 동작을 구현합니다.
Peter Hosey

답변:


80

예, 보장됩니다.

매크로 인수가 매크로 본문에 stringifier # 또는 token-paster ##와 함께 나타나는 경우를 제외 하고 매크로에 대한 인수 자체가 매크로 확장이기 때문에 작동합니다 .

6.10.3.1/1 :

... 함수형 매크로 호출에 대한 인수가 식별 된 후 인수 대체가 발생합니다. 대체 목록의 매개 변수는 앞에 # 또는 ## 전처리 토큰이 있거나 뒤에 ## 전처리 토큰 (아래 참조)이없는 경우 포함 된 모든 매크로가 확장 된 후 해당 인수로 대체됩니다.

따라서 STR1(THE_ANSWER)STR1의 인수가 매크로 확장이 아니기 때문에 "THE_ANSWER"가 표시됩니다. 그러나, STR2의 인수 이 때문에 STR1의 인자를 제공 STR2의 정의로 치환 때 매크로 확장 42"42"의 결과.


21

Steve가 언급했듯이 이것은 보장되며 C89 표준 이후로 보장되었습니다.이 표준은 매크로에서 ### 연산자를 코드화하고 args에서 매크로를 재귀 적으로 확장해야하는 경우에만 본문에 매크로를 대체하도록합니다. 본문은 인수에 # 또는 ## 을 적용하지 않습니다 . 이 점에서 C99는 C89와 동일합니다.


시간을내어 C89의 일부임을 확인하는 데에도 +1입니다. 우리 중 일부는 C89 모드에서 컴파일하는 사람들이 사용할 수있는 코드를 만드는 것을 포함하여 이식성에 관심이 있습니다. 불과 몇 년 전만해도 gcc 릴리스는 여전히 C89 (공평한 gcc 확장 포함)로 기본 설정되었으며, 마지막으로 들었던 MSVC는 여전히 C89 만 지원하며 임베디드 또는 레거시 시스템에는 때때로 C89 컴파일러 만 있습니다. C89는 사람들이 오늘날 실제 사용되는 모든 것을 컴파일하고 실행할 수있는 최소 공통 분모 표준 인 뛰어난 이식성 "1 층"을 만듭니다. 그래서 그것이 기억되는 것을 보는 것이 매우 좋습니다.
mtraceur
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.