程序的每一行都有自己的地址吗?

时间:2016-10-04 17:55:58

标签: c

我在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>的地址是什么,依此类推?

1 个答案:

答案 0 :(得分:3)

函数指针通常被实现为函数入口点的代码地址,但就语言而言,它只是一个可用于调用函数的不透明值。 (并将[in]等式与相同类型的其他函数指针进行比较)。它可以是程序范围或系统范围表的索引,和/或它可能包含额外信息。

该语言不提供查询语句地址的方法;就C标准而言,这个概念甚至不存在。

如果要查看生成的机器代码,可以合理地讨论为给定语句生成的代码的地址。例如,您的陈述

abc

可能对应于ptr = &display; 指令,并且该指令可能具有(机器级)地址,但标准语言无法使用该信息。 MOV语句跳转到指定的语句,并且它的可能使用指令实现,该指令引用该语句的第一条指令的机器地址,但标准为&#39 ; goto的描述并没有在那个细节层面上谈论它;它只描述了语义。

某些编译器(包括gcc)有一个扩展名(documented here),可以让您获取标签的地址。但这仅适用于带标签的陈述。

特别是指令

goto

由编译器的早期阶段处理,通常作为单独的预处理器实现。它引入了许多可由以下代码引用的声明。通常没有与#include <stdio.h> 指令对应的生成代码,因此谈论其地址&#34;无意义。

正如PSkocik在评论中指出的那样,代码生成不一定是线性的;如果编译器能够重新排序以获得更好的速度,则可能没有与给定语句关联的任何代码。 (如果使用gcc扩展名来获取标签的地址,那么编译器可能会在必要时禁止优化以确保该地址有意义。)

就标准C而言,即使您可以获取给定语句的地址,该语言也没有任何可以让您对其执行任何操作的结构;例如,标准#include语句只采用文字标签名称。