对于此代码:
int main(void) {
int a = 1;
int b = 2;
int* pa = &a;
*pa = a + b;
printf("%d", a);
}
在编译时,编译器将计算所需的空间。我们有2个整数和一个指针。就是2*4 + 8 = 16
。然后,它指定给定变量的存储器相对于起点地址的位置。
pa
在起点地址,长度为8个字节。
b
位于起点地址+ 8个字节,长度为4个字节。
a
位于起点地址+ 12个字节,长度为4个字节。
然后执行时间说明:
1
的二进制表示形式放在a
的位置。2
的二进制表示形式放在b
的位置。a
的相对地址(起始地址+ 12个字节)转换为其绝对位置,并将其放置在pa
的位置。a
处获取字节,在位置b
处获取字节,将它们相加,然后在位置pa
处获取字节。将位置pa
处的字节用作地址,并将计算出的总和放在此处。a
上打印字节,然后首先将其转换为十进制数。这是有效的翻译吗?
我们假设使用了超级简单的编译器(没有优化)。它关心的只是有效执行C代码。
答案 0 :(得分:4)
这几乎是一种的翻译方式,(a),尽管通常将函数的局部变量分配在堆栈上,而不是要求操作系统提供一定数量的存储它们的内存。
当然,有了智能编译器,源代码中就有足够的信息可以简单地优化整个过程,直到:
int main(void) { putchar('3'); }
(a) ISO C标准并不指示如何在幕后进行,仅指示它们以某些方式运行。将C视为实现该标准的虚拟机。 VM的工作方式并不重要,当然除了行为之外,其他任何方面都没有强制要求。
答案 1 :(得分:3)
据我了解,是的,这是有效的翻译。不,几乎100%肯定不是您的编译器将要产生的翻译。 C标准具有所谓的as-if rule,这意味着编译器可以自由生成任何程序,其副作用是,就像是为该程序编译的一样。所谓的抽象C机并在其中运行。
实际上,编译器可以生成以下程序:
'3'
放入寄存器中,该寄存器用作函数调用中的第一个参数putchar
main
函数返回对于观察者来说,该程序的副作用与程序的副作用是无法区分的:它打印3
,并以main
作为返回值从0
返回。
答案 2 :(得分:1)
步骤1 变量a
,b
和pa
将在堆栈中分配。因此,不要求操作系统分配内存-您只需要使用堆栈即可,该堆栈由进程本身控制。也许它不会要求16个字节-4个字节就足够了,因为您实际上是在使用变量a
。而且即使那个是常数,也可以用a
代替1
的实例。
步骤4:编译器可能会完全跳过此步骤,因为在下一步中重新分配值之前,您不会使用pa
的值。
步骤6:将两个参数(%d\0
字符串和值1
)推入堆栈并调用名为printf
的函数。不知道它是否输出到终端-也许stdout
正在重定向到文件中?
最后,不可能确切知道将从该源代码生成什么指令。取决于体系结构,操作系统/ OS版本,编译器/ cc版本,编译器标志...