programing

#define에서 ##은 무엇을 의미합니까?

telecom 2023. 7. 24. 22:18
반응형

#define에서 ##은 무엇을 의미합니까?

이 선은 무슨 뜻입니까?특히, 무엇이##비열한?

#define Analyze(변수, 플래그) ((Something).##http) & (http:/(http)

편집:

아직도 약간 혼란스러워요.없는 결과는 무엇입니까?##?

아직도 약간 혼란스러워요.##이 없으면 결과는 어떻게 됩니까?

보통 당신은 어떤 차이도 알아차리지 못할 것입니다.하지만 차이점이 있습니다.라고 가정합니다.Something유형:

struct X { int x; };
X Something;

그리고 다음을 참조하십시오.

int X::*p = &X::x;
ANALYZE(x, flag)
ANALYZE(*p, flag)

토큰 연결 연산자 없음##다음으로 확장:

#define ANALYZE(variable, flag)     ((Something.variable) & (flag))

((Something. x) & (flag))
((Something. *p) & (flag)) // . and * are not concatenated to one token. syntax error!

토큰 연결을 통해 다음과 같이 확장됩니다.

#define ANALYZE(variable, flag)     ((Something.##variable) & (flag))

((Something.x) & (flag))
((Something.*p) & (flag)) // .* is a newly generated token, now it works!

사전 처리기는 텍스트가 아닌 사전 처리기 토큰에서 작동합니다.따라서 두 개의 토큰을 연결하려면 명시적으로 말해야 합니다.

##매크로 호출에서 두 개의 토큰을 연결하는 데 사용되는 토큰 연결이라고 합니다.

참조:

한 가지 매우 중요한 부분은 이 토큰 연결이 몇 가지 매우 특별한 규칙을 따른다는 것입니다.

예: IBM doc:

  • 인수의 매크로가 확장되기 전에 연결이 수행됩니다.
  • 연결 결과가 유효한 매크로 이름이면 일반적으로 사용할 수 없는 컨텍스트에 나타나더라도 추가로 대체할 수 있습니다.
  • 매크로 정의의 대체 목록에 둘 이상의 ## 연산자 및/또는 # 연산자가 나타나면 연산자의 평가 순서가 정의되지 않습니다.

예는 또한 매우 자기 설명적입니다.

#define ArgArg(x, y)          x##y
#define ArgText(x)            x##TEXT
#define TextArg(x)            TEXT##x
#define TextText              TEXT##text
#define Jitter                1
#define bug                   2
#define Jitterbug             3

출력 포함:

ArgArg(lady, bug)   "ladybug"
ArgText(con)    "conTEXT"
TextArg(book)   "TEXTbook"
TextText    "TEXTtext"
ArgArg(Jitter, bug)     3

출처는 IBM 문서입니다.다른 컴파일러에 따라 다를 수 있습니다.

라인으로:

변수 속성을 "Something"에 연결하고 논리적으로 정렬된 변수를 처리하여 Something.variable에 플래그가 설정된 경우 결과로 제공합니다.

그래서 제 마지막 의견과 당신의 질문(g++로 컴파일 가능)에 대한 예를 들어보겠습니다.

// this one fails with a compiler error
// #define ANALYZE1(variable, flag)     ((Something.##variable) & (flag))
// this one will address Something.a (struct)
#define ANALYZE2(variable, flag)     ((Something.variable) & (flag))
// this one will be Somethinga (global)
#define ANALYZE3(variable, flag)     ((Something##variable) & (flag))
#include <iostream>
using namespace std;

struct something{
int a;
};

int Somethinga = 0;

int main()
{
something Something;
Something.a = 1;

if (ANALYZE2(a,1))
    cout << "Something.a is 1" << endl;
if (!ANALYZE3(a,1))
    cout << "Somethinga is 0" << endl;
        return 1;
};

이는 질문에 대한 답변이 아니라 프리프로세서를 직접 탐색하는 데 도움이 되는 몇 가지 팁이 포함된 CW 게시물일 뿐입니다.

사전 처리 단계는 실제 코드가 컴파일되기 전에 실제로 수행됩니다.즉, 컴파일러가 당신의 코드를 만들기 시작하면 #define 문이나 그와 유사한 것이 남지 않습니다.

전처리기가 코드에 대해 수행하는 작업을 이해하는 좋은 방법은 전처리된 출력을 파악하여 확인하는 것입니다.

다음은 Windows용 작업 방법입니다.

test.cpp라는 간단한 파일을 만들어 폴더에 넣습니다(예: c:\temp).내 것은 다음과 같습니다.

#define dog_suffix( variable_name ) variable_name##dog

int main()
{
  int dog_suffix( my_int ) = 0;
  char dog_suffix( my_char ) = 'a';

  return 0;
}

그다지 유용하지는 않지만, 간단합니다.Visual studio 명령 프롬프트를 열고 폴더로 이동한 후 다음 명령줄을 실행합니다.

c:\temp>cl test.cpp /P

즉, 파일과 함께 실행하는 컴파일러(cl.exe)이며 /P 옵션은 컴파일러에게 전처리된 출력을 파일에 저장하도록 지시합니다.

이제 test.cpp 옆의 폴더에 test.i가 있습니다. 이는 다음과 같습니다.

#line 1 "test.cpp"


int main()
{
  int my_intdog = 0;
  char my_chardog = 'a';

  return 0;
}

보시다시피 #define은 남아 있지 않고 확장된 코드만 남아 있습니다.

위키백과에 따르면

토큰 붙여넣기라고도 하는 토큰 연결은 C 매크로 전처리기의 가장 미묘하고 쉽게 악용할 수 있는 기능 중 하나입니다.## 사전 처리 연산자를 사용하여 두 인수를 함께 '접착'할 수 있습니다. 이렇게 하면 두 토큰을 사전 처리된 코드에서 연결할 수 있습니다.이것은 C++ 템플릿의 조잡한 버전처럼 작동하는 정교한 매크로를 구성하는 데 사용될 수 있습니다.

토큰 연결 확인

다른 예를 살펴보겠습니다.

고려하다

#define MYMACRO(x,y) x##y

없이##는 분히전기볼는수없습다니를 볼 수.x그리고.y별도의 토큰으로, 가능합니까?

예를 들어,

#define ANALYZE(variable, flag)     ((Something.##variable) & (flag))

##새 식별자를 만들지 않기 때문에 필요하지 않습니다."."을은 유효한 토큰을 .

언급URL : https://stackoverflow.com/questions/6503586/what-does-in-a-define-mean

반응형