一些一般的C问题

时间:2010-04-03 17:58:29

标签: c programming-languages

我正在努力完全理解将某些语言的代码编写为OS执行的过程。就我而言,语言将是C,操作系统将是Windows。到目前为止,我读了很多不同的文章,但我不确定,我是否理解这个过程是正确的,我想问你是否知道一些关于我找不到的主题的好文章。

所以,我认为我对C(基本上是其他语言)的了解:

C编译器本身只处理数据类型,基本数学运算,指针运算和函数处理。通过使用函数我的意思是如何将参数传递给它,以及如何从函数中获取输出。在编译期间,函数调用被替换为将参数传递给堆栈,而如果函数不是内联函数,则其调用将被链接器的某个符号替换。链接器比找到函数定义,并替换符号跳转到该函数的地址(当然比跳回程序)。

如果以上情况一般都是正确的,我说得对,最终.exe文件在哪里实际上链接器保存了这些功能?在main()函数之后?什么创建.exe标头?编译器还是链接器?

现在,C的其他功能,现在被称为C标准库,是一组函数及其声明,其他程序员编写这些函数来扩展和简化C语言的使用。但像printf()这些函数是(或可能是?)用不同的语言或汇编语言编写的。还有我的下一个问题,例如,printf()函数是用纯C编写的,而不使用汇编程序?

我知道这是一个非常大的问题,但我只是想知道,我是对还是不对。相信我,我在网上阅读了很多文章,我不会问你,如果我能在一个地方,一篇文章中找到这些信息。 Insted我必须逐个收集信息,所以我不确定我是否正确。感谢。

3 个答案:

答案 0 :(得分:6)

我认为你接触到一些与初级C程序员不太相关的信息,这可能让你感到困惑 - 使用这种更高级别语言的部分目标是不必首先考虑如何这个过程有效。但是,随着时间的推移,了解这一过程非常重要。我认为你通常对它有正确的理解。

C编译器只接受C代码并生成包含机器语言的目标文件。大多数目标文件都是由函数的内容获取的。例如,在C中的简单函数调用将在编译形式中表示为低级操作符,以将事物推入堆栈,更改指令指针等。

您将使用的C库和任何其他库已经以此编译形式提供。

链接器是组合所有相关目标文件的东西,解析所有依赖项(例如,一个目标文件调用标准库中的函数),然后创建可执行文件。

至于语言库的编写:将每个函数都想象成一个黑盒子。只要黑盒子有一个标准接口(C调用约定;也就是说,它以某种方式接受参数,以某种方式返回值等),内部写入的方式无关紧要。最典型的是,函数将用C语言编写或直接用汇编语言编写。当它们成为目标文件(或作为编译库)时,它们最初创建的方式并不重要,重要的是它们现在处于已编译的机器形式。

可执行文件的格式取决于操作系统,但Windows中可执行文件的大部分内容与目标文件的大部分相似。想象一下,好像有人将所有目标文件合并在一起然后添加了一些胶水。胶水会加载相关的东西,然后调用main()。例如,当我还是个孩子的时候,人们会在“更换胶水”之后添加另一个功能,然后在main()之前添加一个带有名字的闪屏。

需要注意的一点是,无论您使用何种语言,最终都必须使用操作系统服务。例如,在屏幕上显示内容,管理进程等。大多数操作系统都有一个也可以类似方式调用的API,但其内容不包含在EXE中。例如,当您运行浏览器时,它是可执行文件,但在某些时候,会调用Windows API来创建窗口或加载字体。如果这是你的EXE的一部分,你的EXE将是巨大的。因此,即使在您的可执行文件中,也存在“缺少引用”。通常,这些是在加载时或运行时解决的,具体取决于操作系统。

答案 1 :(得分:1)

我是新用户,此系统不允许我发布多个链接。为了解决这个限制,我在我的博客http://zhinkaas.blogspot.com/2010/04/how-does-c-program-work.html上发布了一些想法。我花了一些时间来获取所有链接,但总的来说,这些应该让你开始。

答案 2 :(得分:0)

编译器负责将用C编写的所有函数转换为汇编程序,并将其保存在目标文件(例如DLL或EXE)中。因此,如果您编写一个具有main函数和一些其他函数的.c文件,编译器会将所有这些函数转换为汇编并将它们一起保存在EXE文件中。然后,当您运行该文件时,加载程序(它是操作系统的一部分)知道首先开始运行main函数。否则,main函数就像编译器的任何其他函数一样。

链接器负责使用其他文件中的引用解析一个目标文件中的函数和变量之间的任何引用。例如,如果调用printf(),因为您没有自己定义函数printf(),链接器负责确保对printf()的调用转到定义了printf()的正确系统库。这是在编译时完成的。

printf()确实是用纯C语言编写的。它的作用是在OS中调用系统调用,它知道如何将字符实际发送到标准输出(如窗口终端)。在程序中调用printf()时,在编译时,链接器负责将调用链接到标准C库中的printf()函数。在运行时传递函数时,printf()会正确格式化参数,然后调用相应的OS系统调用以实际显示字符。