简体   繁体   中英

Cast function to function pointer

typedef void (*LoopCallback)(int fd, void * arg);

LoopCallback func_ptr = 0;

void call_back(int value)
{
    printf("%d", value);
}

void sys_register_input(LoopCallback call_back)
{
    func_ptr = call_back;
}

int main()
{
    sys_register_input((LoopCallback)call_back);
    func_ptr(33, 0);
}

Found this code in one of the legacy project, is this kind of casting valid in c?

Edit : call the function ptr

No, it is not valid. The prototype expected by the caller doesn't match the prototype of the function being called, so undefined behavior may result. The specific result will depend on such factors as the compiler and the calling convention (the called function may merely end up seeing garbage in arg , or the thread stack may get corrupted resulting in a crash).

Andrew Medico is right when he says that it is invalid, but in actual practice, it is certainly going to work on the vast majority of current ABIs, and work reliably.

Most ABIs used today let the caller do all the stack maintenance and/or pass arguments in registers, so if you give a function more arguments than it asks for, noone is going to notice. You're just going to have some unused stack space, or write a value to a register that is never used.

In actual fact, you can often do the reverse as well; that is, to give a function fewer arguments than it asks for. It's going to receive undefined values for those arguments, but if it doesn't use them you'll be alright. In fact, the standard POSIX C function open() depends on this behavior, which goes to show how uncommon it is for C ABIs to choke on these things, both now and historically.

If possible, you should of course avoid relying on this kind of behavior working, but especially if you don't care about being overly portable I don't really see a reason to balk at it. You should , however, be very well aware of what you're doing, and you shouldn't use these kinds of tricks if you don't feel that you are well-versed in the reasons for why they may or may not work.

One occasion where this would not work is if you're writing functions in a Pascal/BASIC-like ABI (like stdcall on Windows), where the caller sets up the stack but the callee cleans it up. In this case, the caller would have pushed two arguments but the callee only pop off one, so the stack pointer would not match its pre-call value after returning, which would cause all kinds of weirdness, including but not limited to the caller function not using the proper return address when it in turn returns. Crashes would be guaranteed. This is quite an unusual thing to do in C, however.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM