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

C 程序的每一行都有自己的地址吗?,c,C,我在学习C语言中的函数指针。我知道函数指针存储函数起点的地址。考虑下面的程序: #include <stdio.h> void display(); int main() { void (*ptr)(); ptr = &display; (*ptr)(); return 0; } void display() { printf("hello"); } #包括 void display(); int main() { 无效(*ptr)(); ptr=&

我在学习C语言中的函数指针。我知道函数指针存储函数起点的地址。考虑下面的程序:

#include <stdio.h>
void display(); 

int main()
{
 void (*ptr)(); 
 ptr = &display;
 (*ptr)(); 
 return 0;
}

void display() 
{
 printf("hello"); 
}
#包括
void display();
int main()
{
无效(*ptr)();
ptr=&display;
(*ptr)();
返回0;
}
无效显示()
{
printf(“你好”);
}

如果
void display()

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

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

如果您想查看生成的机器代码,可以合理地谈论为给定语句生成的代码的地址。例如,你的声明

ptr = &display;
可能对应于
MOV
指令,并且该指令可能有一个(机器级)地址,尽管标准语言无法使用该信息。
goto
语句跳转到指定的语句,它可能是通过引用该语句的第一条指令的机器地址的指令来实现的,但是标准对
goto
的描述并没有在该详细级别上讨论它;它只描述语义

一些编译器,包括gcc,有一个扩展(),允许您获取标签的地址。但这只适用于带标签的语句

特别是,该指令

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

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


就标准C而言,即使您可以获取给定语句的地址,该语言也没有任何结构可以让您使用它做任何事情;标准<代码> Goto 语句,只使用一个文字标签名称。

虽然DUPE被标记为C++,但一般适用于C。如果有人不同意,请告诉我。编译不是线性转换。源代码只能非常粗略地映射到目标代码。函数的开头必须存在,并且将有一个地址。然而,编译将使函数体变得难以识别,这就是我们没有反编译器的基本原因。我无法理解“include的地址大小是多少”。@SouravGhosh它显然不是一个复制品。@KeithThompson:那将是一个撬杆,不是吗?也许有一些链接可以说明C/C++程序如何有助于了解编译和预处理之间的区别,其中包括处理:@JorgeBellón:就标准而言,预处理只是编译的早期阶段。但是我添加了对预处理器的引用。