Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

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

c++ - Calling a function pointer whose assigned function has less arguments then the pointer type

Consider the following code:

#include <iostream>

typedef int (*test_func_t) (int, int, int);

int print_integer (int a)
{
    std::cout << "num: " << a << "
";
    return a;
}

int main (int argc, char * argv[])
{
    test_func_t func = (test_func_t) &print_integer;
    std::cout << "calling with 3 parameters func(5,7,9)
";
    func(5,7,9);
    return 0;
}

As you can see, a type (test_func_t) is defined as a function with 3 int arguments. A function pointer (func) is assigned with a pointer to "print_integer", which receives only 1 argument, and the function pointer is then called with 3 arguments (5, 7, 9).

This code works and produces "num: 5" output.

gdb disas output (Intel syntax)

disas main
...
   0x080486cb <+9>:     mov    DWORD PTR [esp+0x1c],0x804867d
...
   0x080486e0 <+37>:    mov    DWORD PTR [esp+0x8],0x9
   0x080486e8 <+45>:    mov    DWORD PTR [esp+0x4],0x7
   0x080486f0 <+53>:    mov    DWORD PTR [esp],0x5
   0x080486f7 <+60>:    mov    eax,DWORD PTR [esp+0x1c]
   0x080486fb <+64>:    call   eax

disas print_integer
   ...
   0x08048683 <+6>:     mov    DWORD PTR [esp+0x4],0x8048830
   0x0804868b <+14>:    mov    DWORD PTR [esp],0x8049ae0
   0x08048692 <+21>:    call   0x8048530 <std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)@plt>
   0x08048697 <+26>:    mov    edx,DWORD PTR [ebp+0x8]
   0x0804869a <+29>:    mov    DWORD PTR [esp+0x4],edx
   0x0804869e <+33>:    mov    DWORD PTR [esp],eax
   0x080486a1 <+36>:    call   0x80484d0 <std::ostream::operator<<(int)@plt>

As you can see, the rest of the arguments ([ebp+0x12] and [ebp+0x16]) are simply not used.

My questions:

  1. This seems to work on Linux x86 with __cdecl calling convention. Is it safe on other architectures and calling conventions as well?
  2. Does any C/C++ standard allows/defines the result of assigning a function pointer from a function that expects fewer arguments?

Example of such use: node.js's NODE_MODULE registers a function whose type has 3 arguments [exports, module, priv]. It is called with those 3 but formal examples show registering of a function with 1 or 2 arguments.

See Question&Answers more detail:os

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

1 Reply

0 votes
by (71.8m points)

Quoting from the C++11 standard expr.reinterpret.cast 6:

A function pointer can be explicitly converted to a function pointer of a different type. The effect of calling a function through a pointer to a function type (8.3.5) that is not the same as the type used in the definition of the function is undefined.

So, I'd say that it is not safe in general. It is undefined behaviour. That said, I don't know how other implementation of C++ behave in this situation.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...