函数指针的解释

2021-12-13 00:00:00 function pointers c++ typedef

我在理解某些结合函数指针和函数声明的 C++ 语法时遇到了问题,即:

I have a problem with understanding some C++ syntax combined with function pointers and function declarations, that is:

通常,当我们想声明一种函数时,我们会做这样的事情:

Usually when we want to declare a type of function we make something like:

typedef void(*functionPtr)(int);

这对我来说很好.从现在起 functionPtr 是一个类型,它代表指向函数的指针,该函数返回 void 并以 int 值作为参数.

and this is fine for me. From now on functionPtr is a type, that represents pointer to the function, that returns void and takes int by a value as an argument.

我们可以这样使用:

typedef void(*functionPtr)(int);

void function(int a){
    std::cout << a << std::endl;
}

int main() {

    functionPtr fun = function;
    fun(5);

    return 0;
}

然后我们将 5 打印在屏幕上.

And we get 5 printed on a screen.

我们得到了函数fun的指针,我们为函数分配了一些现有的指针――function,然后我们通过一个指针来执行这个函数.很酷.

we have got pointer to function fun, we assign some existing pointer to function - function and we execute this function by a pointer. Cool.

现在,正如我在一些书中读到的那样,函数和指向函数的指针以某种方式被对待函数的类型相同,所以下面的编译和每条指令给出相同的结果(5 打印在屏幕上):

Now as I read in some books, function and pointer to function are treated somehow the same, so in fact after declaration of function() function everytime we say function we mean real function and pointer to function at the same type, so following compiles and every instruction gives the same result (5 printed on a screen):

int main() {

    functionPtr fun = function;
    fun(5);
    (*fun)(5);
    (*function)(5);
    function(5);

    return 0;
}

所以现在只要我能想象,指向函数的指针和指向函数的指针几乎相同,那对我来说就没什么问题了.

So now as long as I can imagine, that pointers to functions and functions are pretty much the same, then it's somehow fine for me.

那么我虽然,如果指向函数和实际函数的指针是相同的,那我为什么不能做以下操作:

Then I though, if pointer to function and real function is the same, then why cannot I do following:

typedef void(functionPtr)(int); //removed *

void function(int a){
    std::cout << a << std::endl;
}

int main() {

    functionPtr fun = function;
    fun(5);

    return 0;
}

这给了我以下错误:

prog.cpp:12:14: 警告:'void fun(int)' 的声明有 'extern' 并已初始化functionPtr fun = 函数;

prog.cpp:12:14: warning: declaration of 'void fun(int)' has 'extern' and is initialized functionPtr fun = function;

因此我明白,由于某种原因编译器现在明白,乐趣是已经存在的功能.然后我尝试了以下操作:

therefore I understood, that for some reason compiler now understands, that fun is already existing function. Then I tried following:

int main() {

    functionPtr fun;
    fun(5);

    return 0;
}

我遇到了链接错误.我以某种方式理解,因为编译器现在将 fun 视为已经存在的函数,然后由于没有定义该 fun 的事实,我将收到链接错误.因此我更改了变量的名称:

And I got linking error. I somehow understand, that as compiler now treats fun as already existing function, then due to the fact, that fun is nowhere defined, I will get linking error. Therefore I changed the name of the variable:

typedef void(functionPtr)(int);

void function(int a){
    std::cout << a << std::endl;
}

int main() {

    functionPtr function;
    function(5);

    return 0;
}

所以现在函数在 main shadows 全局名称函数中,所以 function(5) 用于声明 functionPtr function; 它工作正常并在屏幕上打印 5.

So now function in main shadows global name function, so function(5) is used from declaration functionPtr function; It works fine and prints 5 on the screen.

所以现在我很震惊.为什么会这样?同样具有误导性的是,当函数指针像这样声明时:

So now I am shocked. Why did this happen? Also misleading thing is, that when function pointer is declared like this:

typedef void(*functionPtr)(int);

我可以通过以下方式创建 functionPtr 类型的函数:

i can create function of type functionPtr in following manner:

functionPtr function(int a){
    std::cout << a << std::endl;
}

然而,在声明如下内容时:

whereas, when declaring something like:

typedef void(functionPtr)(int);

使这个:

functionPtr function(int a){
    std::cout << a << std::endl;
}

被编译器解释为函数返回函数.如果是这样,为什么之前的声明 (typedef void(functionPtr)(int);) 知道这是一个返回 void 的函数而不是返回 functionPtr 的函数?

being interpreted by a compiler as function returning function. If this is so, why previous declaration (typedef void(functionPtr)(int);) knew, that this is a function returning void and not function returning functionPtr?

有人可以为我解释一下到底发生了什么吗?

Could someone please explain what is really happening underhood for me?

我正在使用启用了 C++14 选项的 g++ C++ 编译器.

I am using g++ C++ compiler with C++14 option enabled.

推荐答案

嗯,有点混乱.

函数类型和函数类型指针确实是两种不同的类型(不比intint的指针更相似).但是,有一个规则,即函数类型在几乎所有上下文中衰减指向函数类型的指针.这里decaying 松散地表示转换(类型转换和衰减之间有区别,但您现在可能对此不感兴趣).

Function type and pointer to function type are indeed two different types (no more similar than int and pointer to int). However, there is a rule, that a function type decays to pointer to function type in almost all contexts. Here decaying loosely means converted (there is a difference between type conversion and decaying, but you are probably not interested in it right now).

重要的是,几乎每次使用函数类型时,最终都会得到指向函数类型的指针.但是请注意几乎 - 几乎每次都不是总是!

What is important, is that almost every time you use a function type, you end up with pointer to function type. Note the almost, however - almost every time is not always!

而且您遇到了某些情况,但没有这样做.

And you are hitting some cases when it doesn't.

typedef void(functionPtr)(int);
functionPtr fun = function;

这段代码试图将一个函数(不是指针!函数!)复制到另一个函数.但当然,这是不可能的――你不能在 C++ 中复制函数.编译器不允许这样做,我不敢相信你编译了它(你是说你有链接器错误?)

This code attempts to copy one function (not the pointer! the function!) to another. But of course, this is not possible - you can't copy functions in C++. The compiler doesn't allow this, and I can't believe you got it compiled (you are saying you got linker errors?)

现在,这段代码:

typedef void(functionPtr)(int);
functionPtr function;
function(5);

function 不会隐藏任何东西.编译器知道它不是一个可以调用的函数指针,只会调用你原来的function.

function does not shadow anything. Compiler knows it is not a function pointer which can be called, and just calls your original function.

相关文章