当我们在函数原型中放入_stdcall
(调用者不需要清除堆栈)时,是由编译器还是链接器来处理?调用由编译器或链接器处理的约定吗?
回答
调用约定会影响代码生成,因此编译器会处理它。链接器不需要知道这一点。
调用约定是如何调用函数(参数编制具体的机器代码,并清理CTACK)和链接涉及这功能(功能在其地址)来调用。
因此,通常编译器会生成正确的代码,并为确切的函数地址留下“占位符”,然后链接器会将实际地址放在那里。也就是说,所谓的link-time code generation这两个都是由链接器完成的。
函数地址与调用约定无关,那就是说,调用约定是由编译器完成的,对吗? – kern 2011-05-05 14:29:07
@kern:是的,除非涉及LTCG。 – sharptooth 2011-05-05 14:43:00
在某些系统上,目标文件只是一堆数据,符号和补丁点。目标文件将告诉链接器链接代码的第574字节应该被修补以包含符号Foo和Bar之间差别的MSB,并且链接器将这样做,但链接器没有超出要执行的计算。
在其他一些系统上,链接器可能更多地涉及代码生成。例如,一些ARM处理器可以运行使用16位或32位指令集编码的代码。某些类型的代码只能使用32位指令集有效运行;一些将充分运行,但使用16位集更加紧凑。 ARM链接器知道使用每个指令集编写哪些例程,如果使用一个指令集编写的代码尝试调用使用另一个指令集编写的函数,链接器将生成一个名为“veneer”的包装器方法,并具有第一个函数调用。单板将执行调用其他方法所需的操作。即使单板是“代码”,它完全由链接器生成。
编译器和链接器之间确实没有固定的分工。我见过一些系统,“编译器”将程序转换为“中间”形式,并且链接器执行所有真正的代码生成,并根据事物在内存中的位置进行优化。如前所述,还有一些链接器只是一个“修补处理器”。可能在这两个极端之间的每一个可想象的分工可能都存在于某个系统的某个地方。
- 1. AVX寄存器如何由通用调用约定来处理?
- 2. 了解C#编译器如何处理链接linq方法
- 3. OpenCL编译器预处理定义?
- 4. C预处理器与C编译器
- 5. 链接器或加载器如何处理共享库的断开软链接?
- 6. 链接器错误,使用g ++链接到由gcc编译的库,未定义的引用该函数
- 7. Borland C++编译器中的链接DLL
- 8. 栈是由编译器或OS /建筑
- 9. 用C++编译器的欧拉 - 编译器不会在100 x 101后处理
- 10. 从Windows批处理文件调用Intel编译器
- 11. C++编译器(或链接器?)如何知道如何处理cpp和头文件类?
- 12. C++遗传编程:调用链接器/编译器,执行编译后的程序和管道输入/输出
- 13. 混合调用约定编译错误
- 14. redhat:netbeans:g ++:适用于链接器的编译器选项
- 15. Scrapy CrawlSpider - 不能按照特定的链接或自定义的处理器
- 16. 编译器如何处理`(c = getchar())!= EOF`?
- 17. C#编译器:预处理只有
- 18. 编译器处理一个委托
- 19. JIT编译器和异常处理
- 20. 编译器不处理freertos #define代码
- 21. C++“编译器”与预处理
- 22. 编译器如何处理const函数?
- 23. 编译器如何处理注释?
- 24. 转到代码编译链接器错误。我可以手动链接吗?
- 25. 与UI路由器链接的链接
- 26. clang编译器中的标志是什么以定义要由预处理器使用的宏?
- 27. 单处理器或多处理器
- 28. 修身路由器链接调用控制器没有硬编码在地图
- 29. 如何将编译器链接到编辑器
- 30. 编译器/汇编程序如何理解处理器内核寄存器?
希望这些名称的格式不同,以致调用约定中的不一致将导致链接时发生错误。 – 2011-05-05 14:57:19
@James在导入DLL时,您经常需要指定调用约定,并且它们通常以无损的方式命名。 – 2011-05-05 15:01:03
Heffeman如果该函数是'extern“C”',显然,调用约定不能被修改为名称。如果函数是“extern”C++“',那么没有理由不这样做。 – 2011-05-05 15:30:16