-4

我试图了解什么是指向 c 中函数的指针。

我想要一些调用函数指针的详细过程,因此,我可以更好地理解函数指针。

有人可以解释为什么我下面的代码不会崩溃并且有一些有线输出吗?为了缩小范围,我正在寻找类似javap的东西可以解释如何jdk编译我的代码和jvm运行我的代码

  1. void 返回和数字 14,15 或 16 的关系是什么。(void 函数返回)
  2. 我的第二个参数有任何安全问题还是与非初始化 val 相同?

测试.c

#include <stdio.h>
#include <stdlib.h>


static void f(int x, int y){

    printf("x = %d \n",  x );
    printf("y = %d \n",  y );
}

typedef int (*FUNC)(int);

int main(void){

    long int addr = (long int)f;
    printf("%d \n",  (int)((FUNC)addr)(1) );

    return 0;
}

使用编译的 mac os 上的输出i686-apple-darwin11-llvm-gcc-4.2

x = 1 
y = 1479046720 
16 
4

4 回答 4

4

The answer is undefined behavior. You're using two incompatible function pointer types and use one to call the other. (Not to mention storing the pointer in an integer, etc., etc.) Thus, your program invokes undefined behavior, and as such, anything can happen. And the values you get are most probably just random crap from the messed up stack and/or CPU registers.

于 2013-02-03T11:08:07.433 回答
3

You are causing undefined behavior all over the place:

  • You're storing the function pointer in a integer, which isn't guaranteed to work
  • You're casting said integer to a different type of function pointer (fewer parameters) with a different return type
  • You're calling the function with fewer parameters than it expects
  • You take a return value from a function returning void

Trying to make sense of this is just unreasonable, but as a guess since you're using x86:

  • x is populated correctly in the function with the 1 you passed
  • y isn't so it gets a random value, likely some leftover on the stack
  • there's no return value and you get whatever was left in the AX register

Could somebody explain why does my code below not crash and have some wired output

Doing the wrong thing isn't guaranteed to crash your program - there are no guarantees.

于 2013-02-03T11:08:18.147 回答
0

The value 16 you get back in the last output is PROBABLY the number of characters written by printf - as that's what printf returns, and in this case, nothing else happens after that in the function. But like others have said, you're asking what happens, and nobody can really say - it may not work at all, crash and burn, or give you some "random" values as return and printout - it's not defined anywhere, and if you compile the code with a different compiler, different compiler settings or on a different type of hardware, the results will change.

Each time you run the code, it will most likely give you the same result, but make some changes to the code, and unpredictable results will occur.

于 2013-02-03T11:16:32.037 回答
0

要回答这个问题,

有人可以解释为什么我下面的代码不会崩溃

并非所有损坏的代码实际上都崩溃了。可能 f 的参数(和返回值)是在寄存器中传递而不是被压入堆栈,因此预期值和实际值之间的不匹配不会转化为堆栈错位。如果您尝试使用更多参数,足以要求堆栈工作,您可能会遇到崩溃或一些可能危险的行为(毕竟在某些安全漏洞中使用了类似的技术)。

然后为了阐明函数指针的用法,我冒昧地用一些注释重写了代码。

#include <stdio.h>
#include <stdlib.h>

/* We want to be able to print a return value, so we make
   f return something - a long, so as to tell it from int
   - in order to be able to get something back.
*/

static long f(int x, int y){

    printf("x = %d \n",  x );
    printf("y = %d \n",  y );
    return x + y;
}

/* We want the signature of a function returning long, and taking
   two int's, since this is what f() is.
*/
typedef long (*FUNCPTR)(int, int);
typedef long (FUNC)(int, int);

int main(void)
{
    /* We want a pointer to f - it works either way */
    FUNCPTR addr   = f;
    FUNC    *addr2 = f;

    /* addr points to a function taking two ints, so we must pass it
       two ints, and format return as long decimal */

    printf("%ld\n",  addr(5, 7));

    /* addr2 is the same */

    printf("%ld\n",  addr2(5, 7));

    return 0;
}

预期输出:

$ gcc -W -Wall -o test test.c

$ ./test
x = 5
y = 7
12
x = 5
y = 7
12
于 2013-02-03T11:31:26.610 回答