2013-06-12 3 views
2

이것은 리눅스 커널 소스에서 발췌 한 것입니다. stem##은 무엇을 사용하고 있습니까? C에서 처음보고C에서`##`은 무엇을 의미합니까?

#define __pcpu_size_call_return(stem, variable)       \ 
({  typeof(variable) pscr_ret__;         \ 
    __verify_pcpu_ptr(&(variable));         \ 
    switch(sizeof(variable)) {          \ 
    case 1: pscr_ret__ = stem##1(variable);break;     \ 
    case 2: pscr_ret__ = stem##2(variable);break;     \ 
    case 4: pscr_ret__ = stem##4(variable);break;     \ 
    case 8: pscr_ret__ = stem##8(variable);break;     \ 
    default:              \ 
      __bad_size_call_parameter();break;      \ 
    }                \ 
    pscr_ret__;              \ 
}) 
+4

'##'연산자와 같은 기본적인 전 처리기 기능은 C의 모든 책에서 읽을 수있는 내용입니다. 항상 좋은 생각입니다. 이 장소는 주로 * 책을 읽은 후에도 * 가질 수있는 질문에 대한 것입니다. – AnT

+2

또한, 리눅스 커널은 적절하고 읽기 쉬운 표준 C 프로그래밍을 배우고 자 할 때 가장 먼저 살펴 봐야 할 곳입니다. – Lundin

+0

묻는다면 더 적합한 질문 제목을 선택하십시오. 종종 이것이 해결책의 첫 걸음입니다. –

답변

6

## 연산자는 토큰을 형성하기 위해 토큰을 함께 붙이는 전처리 작업입니다.

그래서 공통 접두사를 기반으로 두 개의 함수를 호출하고 매번 단일 인수를 전달하여 변경되도록 허용한다고 가정 해 보겠습니다. 당신은 사용할 수 없습니다

:

#define CallBoth(pref,arg) \ 
{ \ 
    arg = pref A (arg); \ 
    arg = pref B (arg); \ 
} 

치환 prefA (또는 B)입니다 별개의 토큰 때문이다. 마찬가지로, 당신은 사용할 수 없습니다

#define CallBoth(pref,arg) \ 
{ \ 
    arg = prefA (arg); \ 
    arg = prefB (arg); \ 
} 

prefA 또는 prefB의 어떤 대체가 발생하지 때문입니다.

이 작업을 수행하려면 사용 :

#define CallBoth(pref,arg) \ 
    { \ 
     arg = pref##A(arg); \ 
     arg = pref##B(arg); \ 
    }  

및 치환 prefA (또는 B) 하나의 토큰으로 연결됩니다. 그 방법은, 당신이 입력하는 경우 :

CallBoth(xyzzy,intVar); 

가로 번역 될 것입니다 :이 기능이 없으면

{ 
    intVar = xyzzyA(intVar); 
    intVar = xyzzyB(intVar); 
} 

, 함수 이름을 나타내는 하나의 토큰으로 끝낼 수있는 방법이 없습니다. 당신이 참조하고있는 파일의 주석에 명시된 바와 같이


:

/*의 다른 스칼라 크기에 호출되는 함수의 집합으로 기능을 분할하는 기능을 분기 처리 된 개체. */

따라서, 변수의 크기에 의존하는 매크로에 주어지고, 그 중 하나를 호출한다 : stemvariable가 매크로 파라미터로서 공급된다

stem1(variable) 
stem2(variable) 
stem4(variable) 
stem8(variable) 

.또는 이 없으면 __bad_size_call_parameter()이라고 전화 할 것입니다.이 해당 크기입니다.

그래서, 전화 :

char char_var; 
__pcpu_size_call_return(xyzzy,char_var) 

통화가 발생합니다 :

xyzzy1(char_var): 

int int_var; 
__pcpu_size_call_return(xyzzy,int_var) 

통화가 발생합니다 : sizeof(int) == 4

xyzzy4(int_var) 

합니다.

+1

'#'은 "문자열 화",'##'은 "토큰 붙여 넣기"라고 생각합니까? –

+0

@ Paul, 나는 네가 옳을 수도 있다고 생각한다. 실제로, 표준에서는 그냥'#'과'## '연산자를 호출하기 때문에 지금 당장이 표준을 살펴 보겠습니다. – paxdiablo

+0

매우 상세한 답변을 해주셔서 대단히 감사합니다 @ paxdiablo :) –

9

처리기 연산자 ## 매크로 팽창 중에 실제 인수를 연결하는 방법을 제공한다. 대체 텍스트의 매개 변수가 ##에 인접하면 매개 변수가 실제 인수로 바뀌고 ## 및 주변 공백이 제거되고 결과가 다시 스캔됩니다. 예를 들어, 매크로 붙여 넣기는 두 개의 인수를 연결합니다 :

#define paste(front, back) front ## back 

그렇게 paste(name, 1) 토큰 name1을 만듭니다.

관련 문제