programing

함수 포인터 정의가 앰퍼샌드 '&' 또는 아스터리스크 '*'의 수에 관계없이 작동하는 이유는 무엇입니까?

javaba 2023. 1. 29. 20:28
반응형

함수 포인터 정의가 앰퍼샌드 '&' 또는 아스터리스크 '*'의 수에 관계없이 작동하는 이유는 무엇입니까?

왜 다음 기능이 작동합니까?

void foo() {
    cout << "Foo to you too!\n";
};

int main() {
    void (*p1_foo)() = foo;
    void (*p2_foo)() = *foo;
    void (*p3_foo)() = &foo;
    void (*p4_foo)() = *&foo;
    void (*p5_foo)() = &*foo;
    void (*p6_foo)() = **foo;
    void (*p7_foo)() = **********************foo;

    (*p1_foo)();
    (*p2_foo)();
    (*p3_foo)();
    (*p4_foo)();
    (*p5_foo)();
    (*p6_foo)();
    (*p7_foo)();
}

여기에는 이러한 연산자의 모든 조합이 동일한 방식으로 작동할 수 있는 몇 가지 요소가 있습니다.

이 모든 것이 작동하는 근본적인 이유는 함수(예:foo 포인터로 으로 변환할 수 는 함수에 대한 포인터로 암묵적으로 변환할 수 있습니다. ★★★★★void (*p1_foo)() = foo; ★★★★★★★★★★★★★★★★★foo으로 그 에 대한 되어 그 는 「」에 됩니다.p1_foo.

★★★&함수에 적용되면 객체에 적용되었을 때 객체의 주소를 나타내는 것과 마찬가지로 함수에 대한 포인터를 생성합니다.일반 함수에 대한 포인터의 경우 함수와 함수로의 암묵적인 변환 때문에 항상 중복됩니다. 경우든,이 「」의 이유입니다.void (*p3_foo)() = &foo;

★★★*함수 포인터에 적용되면 객체에 대한 일반 포인터에 적용되었을 때 포인팅 대상 객체를 생성하는 것과 마찬가지로 포인트 대상 함수를 생성합니다.

을 사용법예를 들어 .**foo

  • ㅇㅇㅇㅇㅇ,foo는, 그 및 됩니다.*포인터에 되어 함수가 .foo
  • 다음, 그 는 다시 으로 그 와 두 번째 됩니다.* is. function. function. function. . is. is. is. is. is. is. is. is.foo.
  • 그런 다음 함수의 포인터로 암묵적으로 변환되어 변수에 할당됩니다.

개라도 수 요.*이치 .*스스 스 스 스 스 스 스 스 스 스 스 스 스 스 스 스 스 스 스 스 스 스 스 스

사례인 '하다'도 해 볼 수 .&*foo:

  • ㅇㅇㅇㅇㅇ,foo그 자체에 은 단항으로 변환됩니다.*foo
  • 다음, '우리'는& 적용되다foofoo이것은 변수에 할당됩니다.

&할 수 이 포인터에 대한 에 추가할 수 있습니다. 을 사용하다void (**pp_foo)() = &p7_foo;를 참조해 주세요.

★★★★★&&foo하지 않습니다.&foo함수가 아니라 r값인 함수 포인터입니다. ★★★★★★★★★★★★★★.&*&*&*&*&*&*foo있을 &******&foo는 두 표현 '''가 이기 때문입니다.&는 항상 함수에 적용되며 rvalue 함수 포인터에는 적용되지 않습니다.

하시기 바랍니다.* 포인터를 둘 다 '기능 포인터'입니다.둘다(*p1_foo)(); ★★★★★★★★★★★★★★★★★」(p1_foo)();기능-기능 변환으로 인해 동일한 결과를 얻을 수 있습니다.

C는 기본 머신에 대한 추상화일 뿐이며, 이 추상화가 누출되고 있는 장소 중 하나임을 기억하는 것도 도움이 될 것 같습니다.

컴퓨터의 관점에서 함수는 실행되면 다른 명령을 실행하는 메모리 주소일 뿐입니다.따라서 C의 함수는 그 자체가 주소로 모델링되며, 이는 함수가 가리키는 주소와 "동일"한 설계로 이어질 수 있습니다.

& ★★★★★★★★★★★★★★★★★」* 연산입니다.즉, C의 함수로 선언된 는 C의 등가 입니다.func == *func == &func == *&func, 「」입니다.*func == **func 해요, 하다, 하다, 하다, 하다, 하다, 하다.

은 '함수'로 할 수 .int () ★★★★★★★★★★★★★★★★★」int (*)() , , , , , , , , , , , , , , , , , , , , , , , , , .*func,func ★★★★★★★★★★★★★★★★★」&func. 에 전화하고 있습니다부르기(&func)() is is is is is와 func() ★★★★★★★★★★★★★★★★★」(*func)(). Godbolt 링크.

* ★★★★★★★★★★★★★★★★★」&함수 기호에는 아무런 의미가 없으며, 컴파일러는 오류를 생성하는 대신 두 경우 모두 func의 주소로 해석합니다.기호와 포인터로 , 이 함수는 배열 기호와 같이 별도의 포인터로 존재하지 않습니다.&arr is is is is is와 arr실행 시 주소가 있는 물리 포인터가 아니기 때문에 컴파일러 수준의 논리 포인터입니다. ★★★★★★★★★★★★★★★★.*func코드 섹션인 함수 코드의 첫 번째 바이트를 읽고, 컴파일러 오류를 발생시키거나 런타임 오류 분할 장애를 허용하는 대신, 컴파일러에 의해 함수의 주소로 해석됩니다.

&가 취득됩니다( 또는 섹션에 입니다)., 이 경우, 「Pointer」는 「Pointer」의 주소를 취득합니다.funcp ★★★★★★★★★★★★★★★★★」*funcp는 여전히 함수의 주소로 해석됩니다.

" " 를 할 foo 호출하는 수 (*p1_foo)() pi_foo().

아직도 @JamesMcNellis의 답변에 납득이 가지 않는다면, 여기 그 증거가 있다.Clang 컴파일러의 AST(추상 구문 트리)입니다.추상 구문 트리는 컴파일러 내부의 프로그램 구조의 내부 표현입니다.

void func1() {};
void test() {
    func1();
    (*func1)();
    (&func1)();

    void(*func1ptr)(void) = func1;
    func1ptr();
    (*func1ptr)();
    //(&func1ptr)();//error since func1ptr is a variable, &func1ptr is its address which is not callable.
}

아스트:

//func1();
|-CallExpr //call the pointer
| `-ImplicitCastExpr //implicitly convert func1 to pointer
|   `-DeclRefExpr //reference func1

//(*func1)();
|-CallExpr //call the pointer
| `-ImplicitCastExpr //implicitly convert the funtion to pointer
|   `-ParenExpr //parentheses
|     `-UnaryOperator //* operator get function from the pointer
|       `-ImplicitCastExpr //implicitly convert func1 to pointer
|         `-DeclRefExpr //reference func1

//(&func1)();
|-CallExpr //call the pointer
| `-ParenExpr //parentheses
|   `-UnaryOperator //& get pointer from func1
|     `-DeclRefExpr //reference func1

//void(*func1ptr)(void) = func1;
|-DeclStmt //define variable func1ptr
| `-VarDecl //define variable func1ptr
|   `-ImplicitCastExpr //implicitly convert func1 to pointer
|     `-DeclRefExpr  //reference func1

//func1ptr();
|-CallExpr  //call the pointer
| `-ImplicitCastExpr //implicitly convert func1ptr to pointer
|   `-DeclRefExpr //reference the variable func1ptr

//(*func1ptr)();
`-CallExpr //call the pointer 
  `-ImplicitCastExpr //implicitly convert the function to pointer
    `-ParenExpr //parentheses
      `-UnaryOperator //* get the function from the pointer
        `-ImplicitCastExpr //implicitly convert func1ptr to pointer
          `-DeclRefExpr //reference the variable func1ptr

언급URL : https://stackoverflow.com/questions/6893285/why-do-function-pointer-definitions-work-with-any-number-of-ampersands-or-as

반응형