我正在读“简而言之C”,并且有很多类似的句子:
一条语句指定一个或多个要执行的动作,例如 为变量分配值,将控制权传递给函数,或 跳转到另一条语句。
我的问题是“执行”这些操作的是什么?
我在这里已经读到C定义为在抽象机上运行, 所以我的猜测是抽象机器应该执行这些操作,而像gcc这样的实际编译器的工作是确保 如果您根据抽象机的工作方式对程序进行心理评估,那么您将获得与实际情况相同的结果。 运行由编译器生成的目标文件(当然,在大多数情况下,不可能从心理上评估程序,但是我正在讲 理论上在这里)。
那么抽象机器应该直接在预处理之后解释C代码吗? C应该翻译成一些吗 抽象机解释的中间代码?抽象机和C之间到底是什么关系?
什么是 程序可见的抽象机状态?只有主存?如果抽象机真的直接解释C代码,那 对声明进行评估,它们如何更改抽象机的状态?最后一系列问题仅是为了给 您了解C与抽象机之间精确关系的意思。
答案 0 :(得分:8)
抽象机器不存在-毕竟,它实际上是抽象(“思想上或作为思想存在,但没有物理或具体存在” )。抽象机是一种严格遵循标准规则的假想机。
C程序由编译器编译为一台具体的机器,该机器可能(通常确实)具有与抽象机器不同的语义。实际的机器可能具有推测执行,乱序执行和并行性之类的东西。
兼容的编译器必须生成一个可执行文件,该可执行文件在运行时将使observable behaviour as if程序已按照标准规则在所述抽象机中执行。
答案 1 :(得分:5)
抽象程序是程序执行模型的正式C术语。 它与称为Turing machine的抽象模型有关,并且是该语言的核心。抽象机器由整章C17 5.1.2.3程序执行定义,第一行说:
此国际标准中的语义描述描述了 与优化问题无关的抽象机器。
换句话说,抽象机是程序指定结果的模型,与优化无关。它指定表达式的排序(执行顺序),确定是否允许优化的规则以及程序的可观察的行为。
非常简单地说,抽象机指定要读取源代码行,就像从源文件的顶部到底部执行一样。
以这个例子为例:
int a = 1;
int b = 1;
int c = a + b + 1;
printf("%d", c);
抽象机指定首先执行a
和b
的初始化,然后执行int c = a + b + 1;
行,最后执行printf。结果必须为3。这意味着如果编译器影响程序的结果,则不允许它们重新排序。每行;
处都有序列点,必须完成所有先前的计算。
但是,编译器可以自由地先执行子表达式a + b
或先执行b + 1
,因为它们彼此之间没有顺序。未指定评估顺序。同样,它可以在b
之前初始化a
,因为顺序无关紧要。
编译器还可以自由地用c = 1 + 1 + 1;
或c = 3;
替换代码,或仅用printf("3");
替换所有代码。两者都不会影响程序的可观察行为,因此这将是有效的优化。