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


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.