GCC 확장자(#, ##)

2108 단어 GCC###C 언어
먼저 이 두 확장자의 각각의 용도를 말해 보자.'#'은 매크로 문자열화(Stringification)를,'#'은 ## 좌우 양쪽의 라벨을 한데 묶는 것이다(token pasting or token concatenation). 다음은 두 가지 간단한 예부터 시작한다.
4
  #define SSVAR(X,Y) const char X[]=#Y
  SSVAR(InternetGatewayDevice, InternetGatewayDevice.);
위의 이 예는 실질적으로 # 확장자를 빌려
InternetGatewayDevice
의 문자 그룹 초기화, 그 등가 코드
gcc – E 확장 획득)은 다음과 같습니다.
4
  const char InternetGatewayDevice[]="InternetGatewayDevice.";
아래의 이 예는 비교적 흔한데 서로 다른 경로를 여는 데 쓰인다.
  #define DEV_FILE_NAME    "/dev/test_kft"

  #define OPEN_FILE(fd, n) \
  {  \
  	  fd = open(DEV_FILE_NAME ##n, 0); \
 	   if (fd < 0) \
 	   { \
 	      printf("Open device error/n"); \
 	      return 0; \
 	   } \
  }
  OPEN_FILE(fd1, 1);
  OPEN_FILE(fd2, 2);
확장된 등가 코드는 다음과 같습니다.
    { fd1 = open(DEV_FILE_NAME1, 0); if (fd1 < 0) { printf("Open device error/n"); return 0; } };
    { fd2 = open(DEV_FILE_NAME2, 0); if (fd2 < 0) { printf("Open device error/n"); return 0; } };

주의해야 할 것은 ## 확장자는 두 개의 탭을 연결하는 데 사용되지만, 이 두 탭 중 하나는 비워둘 수 없습니다!
그러나 이 두 개의 확장자를 사용하면 오류가 발생하기 쉬운 부분이 하나 있다. 그것이 바로 널리 퍼진 문제이다. 아래의 이 예를 보면 다음과 같다.
    #define xstr(s) str(s)
    #define str(s) #s
    #define foo 4

    str(foo); //->”foo”
    xstr(foo); //->xstr(4)->str(4)->”4”

왜str(foo)와 xstr(foo)가 전개된 후에 완전히 다른 결과가 나타날까요?여기서 매크로 전개 규칙 문제와 관련된다. 매크로 사전 스캐닝(macro prescan) 단계에서 매크로 매개 변수는 먼저 교체되고 교체된 다음에 다음 스캐닝을 통해 마지막 매크로 전개(macro expand)를 완성한다. OK. 이쯤 되면str(foo)는 사전 스캐닝 단계에서str(4)로 바뀔 것 같지만 GCC는 매크로 사전 처리 단계에서 특별히 배외 규칙을 추가했다.매크로 파라미터가 문자열화되거나 다른 탭과 연결되면 대체되지 않습니다.결과도 가히 짐작할 수 있다.다음은 발췌문의 사전 처리 규칙입니다.
    Macro arguments are completely macro-expanded before they are substituted into a macro body, unless they are stringified or pasted with other tokens. After substitution, the en-tire macrobody, including the substituted arguments, is scanned again for macros to be expanded.
【참고문헌】
1. The C Preprocessor (For gcc version 4.7.2)

좋은 웹페이지 즐겨찾기