Typedef 함수 포인터?


458

DLL을 동적으로로드하는 방법을 배우고 있지만 이해하지 못하는 것은이 줄입니다.

typedef void (*FunctionFunc)();

몇 가지 질문이 있습니다. 누군가 대답 할 수 있다면 감사 할 것입니다.

  1. typedef사용됩니까?
  2. 구문이 이상하게 보입니다. 나중에 void함수 이름이나 무언가가 없어야합니까? 익명 함수처럼 보입니다.
  3. 함수의 메모리 주소를 저장하기 위해 함수 포인터가 생성 되었습니까?

그래서 지금 당황합니다. 나를 위해 무엇을 명확히 할 수 있습니까?


5
링크 (마지막 부분)을 살펴보십시오 learncpp.com/cpp-tutorial/78-function-pointers
enthusiasticgeek

9
c ++ 11 using FunctionFunc = void (*)();을 대신 사용할 수 있으므로주의해야합니다 . 타입에 대한 이름을 선언하는 것 (투명 포인터)
user362515

@ user362515에 추가하기 만하면 나에게 좀 더 명확한 형태는 다음과 같습니다.using FunctionFunc = void(void);
topspin

@topspin IIRC이 둘은 동일하지 않습니다. 하나는 함수 포인터 타입이고 다른 하나는 함수 타입입니다. 묵시적 변환이 있습니다. 그것이 작동하는 이유입니다. IANA (C ++) L입니다. 어쨌든, 포인터 유형을 정의하려는 의도가있는 경우 구문 *이 조금 더 명시 적이라고 생각합니다 .
user362515

답변:


463

typedef이름을 형식에 연결하는 언어 구문입니다.
예를 들어 원래 유형과 같은 방식으로 사용합니다.

  typedef int myinteger;
  typedef char *mystring;
  typedef void (*myfunc)();

그들을 사용하여

  myinteger i;   // is equivalent to    int i;
  mystring s;    // is the same as      char *s;
  myfunc f;      // compile equally as  void (*f)();

보시다시피, typedefed 이름을 위에 주어진 정의로 바꿀 수 있습니다 .

어려움은 C와 C ++에서 함수 구문과 가독성에 대한 포인터에 typedef있으며 그러한 선언의 가독성을 향상시킬 수 있습니다. 그러나 다른 더 간단한 유형과 달리 함수는 반환 값과 매개 변수를 가질 수 있으므로 함수에 대한 포인터의 길고 복잡한 선언이있을 수 있으므로 구문이 적합합니다.

가독성은 함수 배열에 대한 포인터와 다른 간접적 인 특징으로 인해 까다로워지기 시작할 수 있습니다.

세 가지 질문에 대답하려면

  • 왜 typedef가 사용됩니까? 코드를 쉽게 읽을 수 있도록-특히 함수 또는 구조 이름에 대한 포인터의 경우.

  • 구문이 이상하게 보입니다 (함수 선언에 대한 포인터에서) . 적어도 시작할 때 구문을 읽을 수 없습니다. 사용하여 typedef선언 대신 읽기를 완화

  • 함수의 메모리 주소를 저장하기 위해 함수 포인터가 생성 되었습니까? 예, 함수 포인터는 함수의 주소를 저장합니다. 이것은 typedef프로그램의 쓰기 / 읽기를 용이하게하는 구성 과는 아무런 관련이 없습니다 . 컴파일러는 실제 코드를 컴파일하기 전에 typedef 정의를 확장합니다.

예:

typedef int (*t_somefunc)(int,int);

int product(int u, int v) {
  return u*v;
}

t_somefunc afunc = &product;
...
int x2 = (*afunc)(123, 456); // call product() to calculate 123*456

6
마지막 예에서 'square'는 동일한 것을 참조하는 것이 아니라 & square를 사용하는 대신 함수를 가리키는 포인터입니다.
pranavk

2
질문, 첫 번째 typedef 예제에서는 형식이 typedef type alias있지만 함수 포인터에는 2 개의 인수 만있는 것 같습니다 typedef type. 별칭이 type 인수에 지정된 이름으로 기본 설정되어 있습니까?
dchhetri

2
@pranavk : 예, square그리고 &square(그리고 실제로 *square**square)는 모두 동일한 함수 포인터를 나타냅니다.
Jonathan Leffler

6
@ user814628 : 당신이 묻는 것이 분명하지 않습니다. 을 (를) 사용 typedef int newname하여 newname에 대한 별칭을 만들고 int있습니다. 를 사용하면 인수를 취하고 값을 반환하는 함수의 포인터 인 에 대한 별칭을 typedef int (*func)(int)만들 수 있습니다 . funcint (*)(int)intint
Jonathan Leffler

10
주문에 대해 혼란스러워합니다. typedef 사용하면 int (*func)(int)func가 별칭이며 별칭이 유형과 얽혀 있기 때문에 약간 혼란 스럽습니다. 로가는 typedef int INT형식 정의 함수 포인터는 형태라면 내가 쉽게 더있을 것입니다 예를 들어 typedef int(*function)(int) FUNC_1. 그렇게하면 하나에 메쉬되는 대신 두 개의 별도 토큰에서 유형과 별칭을 볼 수 있습니다.
dchhetri

188
  1. typedef별명을 지정하는 데 사용됩니다. 이 경우 앨리어싱하고 있습니다 FunctionFuncvoid(*)().

  2. 실제로 구문이 이상하게 보이면 다음을 살펴보십시오.

    typedef   void      (*FunctionFunc)  ( );
    //         ^                ^         ^
    //     return type      type name  arguments
  3. 아니요, 이것은 단순히 컴파일러에게 FunctionFunc유형이 함수 포인터가 될 것이라고 말하며 , 다음과 같이 정의 하지 않습니다 .

    FunctionFunc x;
    void doSomething() { printf("Hello there\n"); }
    x = &doSomething;
    
    x(); //prints "Hello there"

27
typedef새로운 유형을 선언 하지 않습니다 . typedef동일한 유형의 많은 정의 된 이름을 가질 수 있으며 고유 하지 않습니다 (예 : 함수의 과부하). 이름을 사용하는 방법과 관련하여 typedef정의 된 이름이 정의 된 이름과 정확히 동일하지는 않지만 typedef동일한 이름을 가진 여러 개의 정의 된 이름이 동일한 경우가 있습니다.
건배와 hth. -Alf

아 이제 알겠다 감사.
Jack Harvin

4
질문 2에 대한 답은 +1-매우 분명합니다. 답변의 나머지 부분도 분명했지만 그 중 하나가 나를 위해 눈
Michael van der Westhuizen

33

typedef단어가 없으면 C ++에서 선언은 FunctionFunc인수가없는 함수에 대한 포인터 유형 의 변수 를 선언하여을 반환 void합니다.

typedef대신 그것을 사용하여 FunctionFunc해당 유형의 이름으로 정의하십시오 .


5
이것은 정말 좋은 생각입니다. 다른 답변을주의 깊게 읽으면 별칭과 이름의 얽힘에 대한 OP의 혼란을 실제로 다루지 않습니다. 이 게시물을 읽음으로써 새로운 것을 배웠습니다.
Mad Physicist

9

C ++ 11을 사용할 수 있으면 std::functionusing키워드 를 사용할 수 있습니다 .

using FunctionFunc = std::function<void(int arg1, std::string arg2)>;

1
C ++없이 11 using키워드는 것과 같다 typedef std::function<void(int, std::string)> FunctionFunc;사람이 11 ++ C없이 기능의 주위에 다른 래퍼를 원하는 경우에 대비,
최고 마스터

2
#include <stdio.h>
#include <math.h>

/*
To define a new type name with typedef, follow these steps:
1. Write the statement as if a variable of the desired type were being declared.
2. Where the name of the declared variable would normally appear, substitute the new type name.
3. In front of everything, place the keyword typedef.
*/

// typedef a primitive data type
typedef double distance;

// typedef struct 
typedef struct{
    int x;
    int y;
} point;

//typedef an array 
typedef point points[100]; 

points ps = {0}; // ps is an array of 100 point 

// typedef a function
typedef distance (*distanceFun_p)(point,point) ; // TYPE_DEF distanceFun_p TO BE int (*distanceFun_p)(point,point)

// prototype a function     
distance findDistance(point, point);

int main(int argc, char const *argv[])
{
    // delcare a function pointer 
    distanceFun_p func_p;

    // initialize the function pointer with a function address
    func_p = findDistance;

    // initialize two point variables 
    point p1 = {0,0} , p2 = {1,1};

    // call the function through the pointer
    distance d = func_p(p1,p2);

    printf("the distance is %f\n", d );

    return 0;
}

distance findDistance(point p1, point p2)
{
distance xdiff =  p1.x - p2.x;
distance ydiff =  p1.y - p2.y;

return sqrt( (xdiff * xdiff) + (ydiff * ydiff) );
}

1
어떤 상황에서 '&'가 필요합니까? 예를 들어 'func_p = & findDistance'와 'func_p = findDistance'가 동일하게 작동합니까?
Donna

1
함수 이름은 포인터이므로 '&'를 사용할 필요가 없습니다. 다시 말해, 함수 포인터를 고려할 때 '&'는 선택 사항입니다. 그러나 기본 데이터 유형의 경우 '&'를 사용하여 주소를 가져와야합니다.
Amjad

1
'&'가 선택 사항이 될 수 있다는 사실은 항상 이상했습니다. typedef를 사용하여 기본 요소에 대한 포인터를 작성하는 경우 (예 : typedef (*double) p'&'는 선택 사항입니까?
Donna

typedef double* p더블에 대한 포인터를 정의 하기 위해 입력 하고 싶다고 생각합니다 . p기본 변수에서 포인터 를 채우려면 '&'를 사용해야합니다. 참고로, 포인터를 역 참조하기 위해 * <포인터 이름>을 사용합니다. 는 *포인터 (함수 이름) 역 참조와 함수 지침이있는 메모리 블록에 갈 수있는 함수 포인터에 사용됩니다.
Amjad

2

일반적인 구문 의 경우 ANSI C 표준의 부록 A를 볼 수 있습니다 .

거기에서 배 커스 - 나 우어 형식에서, 당신은이 볼 수있는 typedef유형이있다 storage-class-specifier.

유형에서 declaration-specifiers당신은 당신이 문제가되지 않는다 순서있는 많은 지정 유형을 혼합 할 수 있음을 알 수있다.

예를 들어,

long typedef long a;

a대한 별칭으로 유형을 정의합니다 long long. 따라서 철저한 사용에 대한 typedef를 이해하려면 구문을 정의하는 backus-naur 형식을 참조해야합니다 (ISO뿐만 아니라 ANSI C에 대한 올바른 문법이 많이 있습니다).

typedef를 사용하여 함수 유형의 별명을 정의 할 때 함수의 ID를 넣는 동일한 위치에 별명을 넣어야합니다. 귀하의 경우 FunctionFunc호출시 유형 검사가 비활성화되어 아무것도 반환하지 않는 함수에 대한 포인터의 별칭으로 유형을 정의하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.