问题描述
c程序中的函数名称是否是将函数体的起始地址保留在较低级别的变量?
示例:
int x = 0;
int sample(int x,int y) {
////code here
return 0;
}
我猜:
这里的sample是和内存中地址的标识符,该地址保存了该函数在内存中的起点。
解决方法
函数名称是对该函数的某种处理-它是提供调用该函数的一种方式。在许多C实现中,它是函数的机器代码的地址(在正在运行的程序中使用的虚拟内存中)。但是,在某些C实现中,可能是数据结构的地址,它提供有关该功能的更多信息,例如该功能使用的寄存器以及其代码在内存中的位置。
,函数名称仅标识要执行的一系列语句。如果编译器知道那些语句是什么(因为该函数是在名称所在的翻译单元中定义的),则编译器可以自由地用任何其执行将与执行该命令具有相同效果的东西替换调用该函数的表达式。功能。
这种替换的一个简单例子是 inline ,但是编译器以及它认为合适的切片和切块。如果调用位于尾部位置,则可以引入分支语句而不是函数调用。它可以内联函数的一部分,将另一部分保留为一段未命名的代码,该代码从不同的地方调用。 (如果不总是需要非内联部分,通常可以这样做。)还有很多其他可能性。从这个意义上说,函数名称根本不需要标识唯一的对象。
某些函数名称将转换为函数指针,而某些函数名称具有外部链接。在这两种情况下,编译器可能不再知道函数的执行效果。 (对于标准库函数,编译器可以知道,因此标准库函数的调用可能会被执行效果相同的代码替换,就像转换单元中定义的函数一样。)
函数指针是一流的对象,但是尽管语法试图通过自动取消引用函数指针并在必要时将函数名称自动转换为函数指针来对您隐藏,但它们与函数并不相同。创建函数指针后,它必须是一个值,可以从该值派生函数的入口点。 C和C ++都保证指向同一函数的两个函数指针的比较相等,这限制了内部表示函数指针的选项。即使这样,也不能保证它包含该函数实现的内存中的地址。例如,它可能通过指向描述要调用的代码的结构而涉及额外的间接级别,或者它可能是某种蹦床,它懒惰地解决了第一次调用该函数的实现。 (这些技术常用于通过外部链接对函数名称的外部引用。)
如果函数具有外部链接,则可以在其他翻译单元中使用其名称作为调用函数的方式。这意味着名称需要以某种方式与可以调用的代码主体相对应。最终,映射必须允许计算某些机器指令的地址,这将成为函数的入口点。但是该计算不必在编译时进行(很少这样做)。即使您的代码创建了一个函数指针,指针也很可能不仅仅是入口点地址。例如,它可以是跳转表中的重定位条目的地址,也可以是蹦床功能的地址。
简而言之,函数名称和内存中的地址之间的关系比变量名称和内存中的地址之间的关系要少很多,尽管实际上,没有外部链接且从未使用过地址的变量也可能不会对应于一个内存地址。 (例如,该名称可能仅指的是该值的当前位置,而该值恰好暂时占据了硬件寄存器。)
简而言之,虽然很想使用一种计算模型,其中名称是特定内存地址的某种别名,但它不是一个非常精确的模型,可能会导致您对可执行文件的性质做出错误的假设。 / p>