15

鉴于所有原始数据类型和对象都分配了内存,直观地很容易想象指向这些类型的指针。

但是函数指针到底指向哪里呢?鉴于指令被转换为机器代码并驻留在内存中,我们是否应该认为它们指向与函数指令的开头相对应的内存位置?

由于非法内存访问,我们面临许多指针错误。当函数指针指向数据存储器而不是指令存储器时是否会发生错误?

4

5 回答 5

32

函数指针也指向内存,唯一的区别是该内存位置有可执行代码而不是数据。

在许多平台上,如果您尝试执行数据(例如常规内存),您将崩溃或导致异常。这称为数据执行保护 - 一种安全措施,可防止应用程序无意中运行可能被恶意软件放置在那里的不可靠代码。

于 2009-02-28T01:23:13.863 回答
5

函数指针包含函数的地址——无论这对给定系统意味着什么。您可以使用它来间接调用函数,您可以分配和比较函数指针值。您还可以将函数指针转换为另一种指向函数的指针类型,依此类推。

编译器实现函数指针最直接的方法是作为函数的内存地址,大多数编译器都是这样做的,但语言标准没有指定。一些系统(我认为 IBM 的 AS/400 就是一个例子)将附加信息存储在函数指针中。只要正确实现所需的语义,编译器就可以将函数指针作为整数索引实现到描述符表中。

无法取消引用函数指针。函数调用需要一个指针,而不是函数名,作为它的前缀表达式;如果您使用函数名称,则该名称将隐式转换为指针(就语言而言;生成的机器代码可能不同)。因此,程序没有可移植的方法来检测函数指针是否实际包含内存地址。

不可移植,给定一个函数func,您可以执行以下操作:

printf("Address of func is %p\n", (void*)func);

可能会看到一些看起来像人类可读的内存地址表示的东西。但严格来说,函数指针的转换行为void*不是由语言定义的,在某些系统上可能不起作用。

甚至可以将函数指针转换为unsigned char*并检查函数的机器代码,但这远远超出了 C 标准定义的任何内容。

最好将函数指针视为以某种未指定方式引用特定函数的不透明值。

于 2014-03-07T16:24:59.300 回答
3

这是一个代码指针。它指向函数的地址。基本上和你描述的一样。是的,如果你的指针不指向你所期望的,你就会遇到问题。

于 2009-02-28T01:24:05.060 回答
2

函数指针指向函数在内存中的地址。

根据通常分配函数指针的方式,如果您让它们指向数据位置,我会感到惊讶。它们通常不会被强制转换,因此不太可能指向除有效函数之外的任何地方。如果您要大量投放它们,那么这可能是个问题。更有可能的是,您传递给函数的数据是错误的。

于 2009-02-28T01:26:16.443 回答
-3

好吧,我不确定,但考虑到函数是指令(ADD,SUB,JMP)并且它们每个都有十六进制值,我相信你不会改变函数,而只会改变 JMP 指令()......

于 2009-02-28T01:25:28.833 回答