我在C中学习函数指针。我了解到函数指针存储函数起始点的地址。请考虑以下程序:
#include <stdio.h>
void display();
int main()
{
void (*ptr)();
ptr = &display;
(*ptr)();
return 0;
}
void display()
{
printf("hello");
}
如果void display()
的地址存储在ptr
中,那么#include <stdio.h>
的地址是什么,依此类推?
答案 0 :(得分:3)
函数指针通常被实现为函数入口点的代码地址,但就语言而言,它只是一个可用于调用函数的不透明值。 (并将[in]等式与相同类型的其他函数指针进行比较)。它可以是程序范围或系统范围表的索引,和/或它可能包含额外信息。
该语言不提供查询语句地址的方法;就C标准而言,这个概念甚至不存在。
如果要查看生成的机器代码,可以合理地讨论为给定语句生成的代码的地址。例如,您的陈述
abc
可能对应于ptr = &display;
指令,并且该指令可能具有(机器级)地址,但标准语言无法使用该信息。 MOV
语句跳转到指定的语句,并且它的可能使用指令实现,该指令引用该语句的第一条指令的机器地址,但标准为&#39 ; goto
的描述并没有在那个细节层面上谈论它;它只描述了语义。
某些编译器(包括gcc)有一个扩展名(documented here),可以让您获取标签的地址。但这仅适用于带标签的陈述。
特别是指令
goto
由编译器的早期阶段处理,通常作为单独的预处理器实现。它引入了许多可由以下代码引用的声明。通常没有与#include <stdio.h>
指令对应的生成代码,因此谈论其地址&#34;无意义。
正如PSkocik在评论中指出的那样,代码生成不一定是线性的;如果编译器能够重新排序以获得更好的速度,则可能没有与给定语句关联的任何代码。 (如果使用gcc扩展名来获取标签的地址,那么编译器可能会在必要时禁止优化以确保该地址有意义。)
就标准C而言,即使您可以获取给定语句的地址,该语言也没有任何可以让您对其执行任何操作的结构;例如,标准#include
语句只采用文字标签名称。