줄 번호에 따라 이름을 가진 함수를 만드는 C 매크로를 만들고 싶습니다. 나는 다음과 같은 일을 할 수 있다고 생각했습니다 (실제 함수는 중괄호 안에 문이있을 것입니다) :
#define UNIQUE static void Unique_##__LINE__(void) {}
나는 다음과 같이 확장되기를 바랐다.
static void Unique_23(void) {}
작동하지 않습니다. 토큰 연결을 사용하면 위치 지정 매크로가 문자 그대로 처리되어 다음으로 확장됩니다.
static void Unique___LINE__(void) {}
이것이 가능합니까?
(예, 아무리 쓸모 없어 보이더라도 이렇게하고 싶은 진짜 이유가 있습니다).
답변
문제는 매크로 대체가있을 때 스트링 화 연산자 #
나 토큰 붙여 넣기 연산자 ##
가 적용 되지 않은 경우에만 전처리 기가 매크로를 재귀 적으로 확장 한다는 것입니다. 따라서 간접적 인 추가 레이어를 사용해야합니다. 토큰 붙여 넣기 연산자를 재귀 적으로 확장 된 인수와 함께 사용할 수 있습니다.
#define TOKENPASTE(x, y) x ## y
#define TOKENPASTE2(x, y) TOKENPASTE(x, y)
#define UNIQUE static void TOKENPASTE2(Unique_, __LINE__)(void) {}
그런 다음, __LINE__
확대시 행 번호로 확장됩니다 UNIQUE
(이 중 하나에 참여하지 이후 #
또는 ##
), 다음 토큰 붙여 넣기의 확장시에 발생TOKENPASTE
.
또한 같은 줄에 __COUNTER__
여러 UNIQUE
매크로 인스턴스화가 필요한 경우 평가 될 때마다 새 정수로 확장 되는 매크로 도 있다는 점에 유의 해야합니다 . 참고 : __COUNTER__
MS Visual Studio, GCC (V4.3 이후) 및 Clang에서 지원되지만 표준 C는 아닙니다.
답변
GCC는 결과가 “문자열 화”될 필요가없는 한 “래핑”(또는 실현)을 요구하지 않습니다. Gcc에는 기능이 있지만 모든 것은 일반 C 버전 1로 수행 할 수 있습니다 (일부는 Berkeley 4.3 C가 사용 방법을 배우는 것이 훨씬 더 빠르다고 주장합니다).
** Clang (llvm)은 매크로 확장을 위해 올바른 공백을 사용하지 않습니다. 공백을 추가합니다 (추가 사전 처리를 위해 C 식별자가되는 결과를 확실히 제거함) **, clang은 단순히 # 또는 * 매크로 확장을 수행하지 않습니다. C 전처리 기는 수십 년 동안 예상됩니다. 가장 좋은 예는 X11을 컴파일하는 것입니다. 매크로 “Concat3″이 손상되었습니다. 결과는 이제 MISNAMED C 식별자이며, 물론 빌드에 실패합니다. 그리고 나는 그들의 직업이 실패하기 시작했습니다.
여기에 대한 대답은 “표준을 깨는 새로운 C는 나쁜 C입니다”라고 생각합니다. 이러한 해킹은 항상 (클로버 네임 스페이스) 이유없이 기본값을 변경하지만 실제로 “C를 개선”하지는 않습니다 (자신의 말을 제외하고는 다음과 같습니다. 아직 아무도 책임을지지 않은 모든 파손으로 도망 치는 이유를 설명하기 위해 만들어진 장치입니다).
이전 C 전처리 기가 UNIq _ () __를 지원하지 않았다는 것은 문제가되지 않습니다. 왜냐하면 그들은 “코드의 컴파일러 브랜드 해커가 해커로 표시 될 수 있도록”허용하는 #pragma를 지원하고 또한 표준에 영향을주지 않고 잘 작동합니다. 기본값은 쓸모없는 완탕 파손이며 동일한 이름을 사용하는 동안 함수가 수행하는 작업을 변경하는 것과 마찬가지로 (네임 스페이스 클로버 링) …