2012-02-20 4 views
9

적어도 typedef와 함수 포인터에 대해서는 "우연한 프로그래머"라는 두려운 질병으로 고통 받고 있다고 생각합니다. 그래서 나는 내가 얻은 모든 결과를 기반으로 결과를 분석하기 위해 이들을 포함하는 모든 종류의 조합을 실험 해왔다.typedef가 함수 포인터로 작동하는 방법

하지만 다른 조합을 시도하면서 결과를 분석하는 대신 지금은 처리 과정에서 길을 잃었습니다.

여러분이이 혼란을 이해하는 데 도움이되기를 바랍니다.

첫 번째 코드 예제

typedef void (print)(void); 
void do_something (void) { printf("Hello World\n"); } 

print *pr; 
pr = &do_something; 
pr(); // Hello World 

두 번째 코드 예

typedef void (print)(void); 
void do_something (void) { printf("Hello World\n"); } 

print *pr; 
pr = do_something; 
pr(); // Hello World 

어떻게 두 예제가 작동 위의 코드는,이 함수 이름

에 영향을주지 않습니다 '&'처럼입니다

제 3 코드 예를

typedef void (print)(void); 
void do_something (void) { printf("Hello World\n"); } 

print pr; 
pr = do_something; // compile error 
pr = &do_something; // compile error 
pr(); 

내가 여기서 일하지만 젠장 위의 과제 중 하나를 기대했다! 필자는 함수 포인터를 이해하지 못한다.

+1

이 도움이 될 수 있습니다 http://stackoverflow.com/questions/4298654/operator-optional-in-function-pointer-assignment –

+0

음 ... 나는 당신이 '전문가 C 프로그래밍'explians C의 var 규칙을 정의하십시오. 나는 당신을 위해 그것을 온라인으로 찾으려고 노력할 것입니다 – shengy

+1

그냥 Google 전문가 C 프로그래밍, 첫 번째 책입니다. '어떻게 선언문이 형성 되었는가?'를 검색하면 – shengy

답변

18

함수 이름과 일반 함수 이름의 주소는 모두 같은 의미이므로, &은 함수 이름에 영향을 미치지 않습니다.

#include <stdio.h> 
typedef void print(void); 
static void dosomething(void) { printf("Hello World\n"); } 

int main(void) 
{ 
    print *f1 = dosomething; 
    print *f2 = &dosomething; 
    f2(); 
    (f1)(); 
    (*f1)(); 
    (**f2)(); 
    (***f1)(); 
    (****f2)(); 
    (*****f1)(); 
} 

에서 깨끗하게 컴파일 : 함수 포인터를 사용하는 경우 마찬가지로

는 여러 역 참조 문제가되지 않습니다

gcc -O3 -g -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \ 
    -Wold-style-definition -std=c99 xx.c -o xx 

내가 그 여러 별을 주장 할 것이 좋은 스타일이다; 그렇지 않습니다. 그것은 '이상하고, (예, 당신이 말할지도 모른다) 비뚤어진'것입니다.그 중 하나는 충분합니다. (그리고 한 스타는 주로 C와 같은 프로그래밍을 배우기 전에 표준을 쓰기 전에 "(*pointer_to_function)(arg1, arg2) 표기법을 사용하지 않고 포인터를 통해 함수를 호출하는 것이 좋으며 원하는 경우"pointer_to_function(arg1, arg2)을 쓸 수 있습니다.). 예, 이상합니다. 아니요, 다른 유형 (또는 유형의 클래스)은 동일한 행동을 보이지 않습니다. 선량님께 감사드립니다.

+1

이제 이상하게 들릴 수도 있습니다. 시도하고 실제로 컴파일하십시오. :) –

+4

+1, 함수와 함수 포인터는 동일하지 않지만, 전자는 대부분의 상황에서 자동적으로 후자로 감쇠하는 경향이 있습니다. '** f2'라는 표현식에서, 함수 포인터는 역 참조되고 그 결과 함수는 즉시 포인터로 쇠퇴합니다. 포인터는 다시 역 참조됩니다. – avakar

+2

배열은 "자동 붕괴"동작과 비슷하지만 비슷하지 않습니다. 'int x [10];'에 대해서'x'와'& x'의 주소는 같습니다. 그러나 그들의 유형은 다르며 여기에 보이는 멋진 별의 탑을 사용할 수 없습니다. – ugoren

3

C/C++에서 funcname&funcname 모두 주소가 funcname이고 함수 포인터 변수에 할당 될 수 있습니다. 이것은 실제로 구문이 언어에 대해 어떻게 설계되었는지에 대한 이상한 점입니다.

7

함수 포인터에 대한 것은 함수라는 것입니다. 포인터!

#include <stdio.h> 
typedef void (*print)(void); 
//   ^
void do_something (void) { printf("Hello World\n"); } 
int main (void) { 
    print pr; 
    pr = do_something; // &do_something would also work. 
    pr(); 
    return 0; 
} 

당신이 funcName 또는 &funcName 사용 여부의 관점에서, 그것은 중요하지 않습니다 (C에서 최소) :이 :-)는 세 번째 샘플이 작동하도록하는 방법이다. 섹션 6.3.2.1 Lvalues, arrays and function designators 상태 :

함수 지정자는 함수 유형이있는 표현식입니다. sizeof 연산자 또는 단항 & 연산자의 피연산자를 제외하고 "함수 반환 형식"유형의 함수 지정자는 "함수 반환 형식에 대한 포인터"형식을 가진 식으로 변환됩니다.

+0

첫 번째 투표가 downvote 인 것을 미친 듯이 보게 될 것이라고 생각합니다. -/ –

3

C와 마찬가지로 C++에는 함수 포인터가 있습니다. 예를 들어, void (*)()은 인수를 취하지 않고 값을 반환하는 함수에 대한 포인터입니다. 그러나 C++은 함수 void (&)()에 대한 참조를 도입했으며 두 규칙 사이에 암시 적 변환이 있습니다 (그러나 규칙은 정확하게 기억하지 못함).

따라서 :

  • funcname
  • &funcname 어드레스 (또는 참조) 과부하 기능을 고려하여 필요하다고

주 함수에 대한 포인터 함수에 대한 참조 인 정확한 유형으로 static_cast (과부하를 해결하기 위해).

관련 문제