2012-11-17 1 views
3

나는 속도를 내재적으로하는 카이 제곱 프로그램을 걷고 이해하려고 노력하고있다. 이 과정에서 저는 이해할 수없는 코드를 발견했습니다.신비한 C++ 구문

나는 교과서, Google 및 행운이 사이트 검색을 검토해 보았습니다. 문제는 구문에 대해 알지 못해도 관련 검색어를 검색 할 수 없다는 것입니다. 여기

코드의 라인이 이해가 안이다 :

float (*chi2_float)(const int, const float*, const float*) = chi2_baseline_float; 

을 그리고 여기에 포함 된 기능입니다 :

float chi2_float(const int dim, const float* const x, const float* const y) { 
    float (*chi2_float)(const int, const float*, const float*) = chi2_baseline_float; 
#ifdef __SSE__ 
    chi2_float = chi2_intrinsic_float; 
#endif 
    return chi2_float(dim, x, y); 
} 

그것은 아마 선언하고 정의하는 것을 나에게 보인다는 함수와 내가 줄을 주석으로 처리하고 다시 컴파일하면 다음과 같이 표시됩니다.

오류 C2659 : '=': 왼쪽 피연산자로 사용 온라인으로 chi2_float = chi2_intrinsic_float;

필요할 경우이 함수가 포함 된 .h 파일을 보낼 수 있지만 매개 변수에서 예상하는대로입니다.

도움을 주시면 감사하겠습니다.

+3

너무 신비스럽지 않습니다. 함수 포인터 일뿐입니다. 당신의 C++ 교과서를 편리하게 얻었습니까? –

답변

11

해당 라인은 __SSE__ 값에 따라 function 포인터 유형의 변수를 다른 두 함수 중 하나에 설정하고 있습니다.

그런 다음 chi2_float가 가리키는 함수를 호출하고 결과를 반환합니다.

+0

감사합니다. 이제 내가 이해하는 타입 함수 포인터를 알았습니다. –

7

이 :

float (*chi2_float)(const int, const float*, const float*)= chi2_baseline_float; 

는 이름을 chi2_float을 함수 포인터를 선언하고 여기에 chi_baseline_float라는 이름의 함수에 대한 포인터를 할당.

그런 다음 __SSE__ 매크로가 정의되면 포인터는 함수 chi2_intrinsic_float에 대한 포인터로 다시 할당됩니다. 일부 의견

float chi2_float(const int dim, const float* const x, const float* const y) 
{ 
#ifdef __SSE__ 
    return chi2_intrinsic_float(dim, x, y); 
#else 
    return chi2_baseline_float(dim, x, y); 
#endif 
} 
+3

비슷하지만 같지 않습니다. 불행하게도, 질문에있는 코드는 간접적 인 수준을 추가 할뿐만 아니라 가능한 인라인 최적화를 방지하는 함수 포인터를 통해 호출되기 때문에 효율적이지 않습니다. 그것을 비교 한 코드는 더 빨라야하며 가능하다면 OP가 그의 코드를이 예제로 대체 할 것을 권장합니다. – cdhowie

+0

+1. 클리너, 짧고, 더 좋고, 빠릅니다. 어떻게 잃을 수 있니? –

+0

감사합니다. Michael Burr. 나는 당신에게 제안을하고 코드를 재실행하고있다. 훨씬 깨끗하고 이해할 수 있습니다. –

1

질문의 코드 :

// beginning of the definition of function chi2_float 
float chi2_float(const int dim, const float* const x, const float* const y) { 
    // declare the variable chi2_float as a function pointer 
    // set variable chi2_float to the address of the function chi2_baseline_float 
    float (*chi2_float)(const int, const float*, const float*) = chi2_baseline_float; 
// if macro __SSE__ is defined (if the compiler enables SSE instructions set) 
// [this is your case because you got an error in the below line when you have commented the above line] 
#ifdef __SSE__ 
    // then preprocessor adds the following line that sets again the variable chi2_float (but to another function) 
    chi2_float = chi2_intrinsic_float; 
#endif 
    // call the function pointed by the variable chi2_float 
    return chi2_float(dim, x, y); 
} 
+0

감사합니다. 귀하의 의견은 매우 모범적이며 "신비한"구문을 쉽게 이해할 수있게 해줍니다. –

+0

안녕하세요. @JamesCrow ;-) 곧 다른 질문/답변을 참조하십시오 ;-) – olibre

1
float chi2_float(const int dim, const float* const x, const float* const y) { 
    float (*chi2_float)(const int, const float*, const float*) = chi2_baseline_float; 
#ifdef __SSE__ 
    chi2_float = chi2_intrinsic_float; 
#endif 
    return chi2_float(dim, x, y); 
} 

미운

모든이의 순 효과는 비슷한입니다.

이 코드를 수정하기 위해해야 ​​할 일은 함수 포인터 변수의 이름으로 함수 이름 이외의 것을 사용하는 것입니다. 이 변수가 함수의 이름을 어둡게한다는 것은 제임스 크로우의 혼란의 근원이라고 생각합니다.

이 코드를 수정하기 위해 수행해야 할 두 번째 작업은 함수 포인터를 완전히 없애고 코드 Michael Burr의 답을 얻는 것입니다.

+0

David Hammen에게 감사드립니다. 당신이 맞습니다, 나는 그 함수 이름과 함수 포인터 변수 이름을 갖는 것이 내 혼란에 추가되었다고 생각한다. –

1

마이클 버는 다음과 같은 제안 :

float chi2_float(const int dim, const float* const x, const float* const y) 
{ 
#ifdef __SSE__ 
    return chi2_intrinsic_float(dim, x, y); 
#else 
    return chi2_baseline_float(dim, x, y); 
#endif 
} 

잠시 컴파일러의 최적화를 무시를; 이것은 향상 될 수 있습니다. Burr의 솔루션은 main() (또는 무엇이든)이 chi2_float()를 호출하여 적절한 구현을 호출하는 두 가지 함수 호출을 사용합니다. 그 다음에 하나의 함수 호출에 줄일 수 있습니다

#ifdef __SSE__ 
    #define chi2_float(dim, x, y) chi2_intrinsic_float(dim, x, y) 
#else 
    #define chi2_float(dim, x, y) chi2_baseline_float(dim, x, y) 
#endif 

같은 결과는 것 "인라인"로 씨 버의 chi2_float()를 선언함으로써 달성 될 수있다.

하지만 실제 세계로 돌아 가면 (컴파일러가 코드를 적극적으로 최적화하는 경우) 좋은 옵션이 추가 함수 호출을 제거해야하므로 Burr의 솔루션이 그렇게 빨리 구현 될 것입니다.

나는이 토론을 completeness에 게시했습니다. 미스터 버 (Burr)의 해결책이 개선되지는 않지만 조금 더 많은 문맥이 추가됩니다. 엄밀히 말하면 새로운 대답이 아니라 주석이되어야하지만 주석의 소스 코드를 형식화 할 수는 없습니다. 그런 삶입니다.

+0

감사합니다. Michael J가 대답했습니다. 마이클 버 (Michael Burr)가 제안한대로 코드를 변경하려고합니다. 아마도 코드를 하나의 함수 호출로 축소 할 것이지만 전반적인 로직을 더 먼저 이해할 필요가 있습니다. –