2015-01-27 3 views
2

저는 약간의 코드를 연구 해왔고 이해할 수있는 약간의 코드를 발견했습니다. 그러나 왜 그렇게했는지는 생각할 수 없습니다. 왜 함수 포인터로 포인터를 캐스팅해야합니까?

나는 아래의 코드의 상황을 재현 :

include <stdio.h> 

void printsum(int x, double y) 
{ 
    printf("Soma: %.2f\n", (double)x + y); 
} 

typedef int int_alias; 

typedef void (* funcptr) (int_alias x, double y); 
typedef void (* fptr) (int x, double y); 

fptr pptr = &printsum; 

#define A_MACRO(x, y) ((funcptr) (pptr)) (x, y) 

int main() 
{ 
    int a = 10; 
    double b = 2.2; 

    A_MACRO(a, b); 
    /* ((funcptr) (pptr)) (a, b); */ 

    return 0; 
} 

이벤트가 발생하고 매크로를 호출 할 때이 작업이 완료되기 때문에, 인쇄 기능이 콜백 함수입니다.

내가 이해하지 못하는 것은 매크로 때문에 일어나는 주조입니다. pptr은 이미 함수 포인터이므로 funcptr으로 다시 캐스팅하는 이유는 무엇입니까?

저는 이런 종류의 건축에 ​​익숙하지 않습니다. 그래서 내가 누락 된 부분 일 수 있습니다. 누군가 이것에 관해 어떤 것을 알려줄 수 있습니까?

+1

결과는이 캐스팅없이 동일하게 나타날 것이라고 생각합니다. –

+0

이상하게 보입니다 ... 원본 코드에 대한 링크를 공유 할 수 있습니까? – mafso

+0

'#define A_MACRO (x, y) (pptr) (x, y)'도 작동합니다. 주조가 필요하지 않습니다. 이 경우에는 코드의 가독성을 향상시키기 위해 수행됩니다. –

답변

1

funcptrfptr는 함수 포인터, 그래 모두 별명,하지만 그들은 int_alias의 정의에 따라 다른 인수 유형를 갖는 기능 에 대한 포인터 될 수 있습니다.

int_aliasint (또는 그에 상응하는 signed int) 이외의 다른 무엇이라도 typedef되면 캐스트가 위험합니다. 포인터 값은 캐스트에 관계없이 유지되지만 캐스트 포인터를 통해 함수를 호출하면 A_MACRO()은 정의되지 않은 동작을 생성합니다.

"int 이외의 항목에는 열거 형이 포함됩니다. 열거 형의 값은 암시 적으로 int으로 변환 될 수 있지만 열거 형은 이 아니며int이 아닙니다. int보다 좁은 열거 형 형식의 표현을 구현에 사용할 수 있기 때문에 이는 진정한 의미와 구별됩니다. 예를 들어, GCC는 값 범위와 컴파일러 옵션에 따라 다양한 열거 형의 너비와 부호가 다른 표현을 선택할 수 있습니다.

요약하면 A_MACRO()에 의해 수행 된 캐스트는 합법적이지만 유용한 용도로 사용되지 않습니다. 그것은 실제로 해로울 수 있습니다. 원래 작성한 사람은 코드를 다른 정수 유형 (int_alias typedef를 통해)에 적용하는 데 도움을 주려고했지만 실제로는 발생하기를 기다리는 버그입니다. 더 좋은 대안이 될 것입니다 ...

#define A_MACRO(x, y) ((pptr) ((int) x, y)) 

... 또는 단순히를 ...

#define A_MACRO(x, y) ((pptr) (x, y)) 

... 주요 포인트는 함수를 통해 호출되고 있다는 사실을 숨길 경우 포인터.

+0

'gcc'는 기본적으로'enum'에'unsigned int' (또는 음수 상수가있는 경우'int')를 사용합니다 (C 컴파일시에는 C++에 대해서는 확실하지 않음) 그리고'(unsigned) char/short' 만 사용합니다 '-fshort-enums'. (일부 타겟의 기본값이 다를 수 있습니다.) – mafso

+0

@mafso, 감사합니다. 그에 따라 내 의견이 수정되었습니다. 나는 원래의 코멘트를 만들 때 잘못된 문서를보고있었습니다. –

관련 문제