Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
337 views
in Technique[技术] by (71.8m points)

c++ - Explanation of function pointers

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);

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.

We can use it as follows:

typedef void(*functionPtr)(int);

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

int main() {

    functionPtr fun = function;
    fun(5);

    return 0;
}

And we get 5 printed on a screen.

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

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;
}

This gives me following error:

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;
}

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;
}

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);

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);

makes this:

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

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?

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Well, it is confusing a bit.

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;

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?)

Now, this code:

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

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...