鉴于所有原始数据类型和对象都分配了内存,因此可以直观地想象出这些类型的指针。
但是函数指针到底指向哪里?鉴于指令被转换为机器代码并驻留在内存中,我们是否应该考虑它们指向与函数指令开头相对应的内存位置?
由于非法内存访问,我们在指针中遇到很多错误。当函数指针指向数据存储器而不是指令存储器时,是否会发生错误?
答案 0 :(得分:29)
函数指针也指向内存,唯一的区别是该内存位置有可执行代码而不是数据。
在许多平台上,如果您尝试执行数据(例如常规内存),您将崩溃或导致异常。这称为数据执行保护 - 一种安全措施,可防止应用程序无意中运行可能由恶意软件放置的狡猾代码。
答案 1 :(得分:4)
这是一个代码指针。它指向函数的地址。它基本上就像你描述的那样。是的,如果你的指针没有指向你的预期,你就会遇到问题。
答案 2 :(得分:2)
函数指针指向内存中的address of the function。
基于通常分配函数指针的方式,如果你让它们指向数据位置,我会感到惊讶。它们通常不是强制转换的,因此不太可能指向除有效函数之外的任何地方。如果你经常施展它们,那么这可能是一个问题。但更可能的是,传递给函数的数据是错误的。
答案 3 :(得分:2)
函数指针包含函数的地址 - 对于给定系统而言意味着什么。您可以使用它间接调用函数,您可以分配和比较函数指针值。您还可以将函数指针转换为另一种指向函数的指针,依此类推。
编译器实现函数指针的最简单方法是作为函数的内存地址,大多数编译器都这样做,但语言标准没有指定。有些系统(我认为IBM的AS / 400就是一个例子)在函数指针中存储了附加信息。只要正确实现了所需的语义,编译器就可以将函数指针实现为描述符表中的整数索引。
无法取消引用函数指针。函数调用需要指针而不是函数名作为其前缀表达式;如果使用函数名,则该名称将隐式转换为指针(就语言而言;生成的机器代码可能不同)。所以程序没有可移植的方法来检测函数指针是否实际包含内存地址。
非便携式,给定函数func
,您可以执行以下操作:
printf("Address of func is %p\n", (void*)func);
并且你可能会看到类似于人类可读的内存地址表示的内容。但严格地说,函数指针转换为void*
的行为不是由语言定义的,它可能在某些系统上不起作用。
你可能甚至能够将函数指针转换为unsigned char*
并检查函数的机器代码,但远远超出C标准定义的任何内容。
最好将函数指针视为不透明值,以某种未指定的方式引用特定函数。
答案 4 :(得分:-3)
嗯,我不确定,但考虑到函数是指令(ADD,SUB,JMP),并且每个函数都有十六进制值,我相信你不会改变函数而只改变JMP指令()。