我还是不太了解。例如,诸如printf()
和scanf()
之类的标准C函数处理将数据发送到标准输出或从标准输入获取数据。实现这些功能的源代码会有所不同,这取决于我们是将它们用于Windows还是Linux?
我想快速的答案是“是”,但是它们真的必须有所不同吗?
我可能错了,但是我的猜测是实际的功能代码是相同的,但是最终被这些功能调用的OS的底层功能是不同的。因此,任何编译器都可以编译这些相同的C函数,但是正是这些链接赋予了我们所需的行为(这些函数依赖于在较低层上工作)?
答案 0 :(得分:1)
实现这些功能的源代码是否会不同 取决于我们是在Windows还是Linux上使用它们?
可能是。在不同的Linux和不同的Windows程序上,它甚至可能有所不同。 C标准库有几种不同的实现可用于Linux,对于Windows甚至可能不止一种。不同的实现将具有不同的实现代码,否则律师会介入。
我的猜测是实际的功能代码是相同的,但是较低 最终被这些调用的操作系统的层功能 功能不同。所以任何编译器都可以编译这些相同的C 功能,但它是链接后的内容(这些功能是什么 取决于在较低的层上工作)是什么给了我们所需的 行为?
可以想象的是,标准库函数的编写方式可以将环境依赖关系抽象到一些较低的层,以便每个函数本身的相同源可以在多种环境中使用,并且具有某种环境-下面的特定兼容性层。由于GNU C库支持各种各样的环境,尽管Windows不在它支持的环境之内,它还是一般原则的一个示例。但是,即使那样,即使在链接阶段之前,环境区分也是有效的。不同的环境具有多种二进制格式。
但是,实际上,您不太可能看到针对Windows和Linux所描述的情况。
答案 1 :(得分:0)
是的,它们有不同的实现方式。
此外,您可能在同一OS上使用多种不同的实现。例如:
很明显,这意味着社区中存在一些代码重复,但这有很多充分的理由:
printf
可能需要或可能不需要使用某些线程同步机制。有些人需要语言环境支持,有些则不需要。所有这些最终都会使代码膨胀,并不是每个人都愿意为不使用的东西付费。甚至strerror
也是vastly different on different OSes。
'e'
模式说明符以打开带有O_CLOEXEC
标志的文件。这对于Windows没有意义。最后,拥有许多C库比尝试创建一种“一刀切”的实现要简单得多。
答案 2 :(得分:0)
正如您所说,诸如printf之类的实现的高层部分,例如使用参数格式化字符串的代码,可以以跨平台的方式编写,并且可以在Linux和Windows之间共享。我不确定是否确实有C库可以实现此功能。
但是要与硬件交互或使用其他操作系统功能(例如,在printf写入控制台时),libc实现必须使用操作系统的接口:system calls。这些在Windows和类Unix之间是非常不同的,甚至在类Unix之间也有所不同(POSIX指定了很多,但是有特定于OS的扩展)。例如,您可以在这里找到Linux和Windows的系统调用表。
答案 3 :(得分:0)
printf()之类的功能有两部分。第一部分分析格式字符串,并组装一个准备输出的字符数组。如果这部分是用C编写的,则没有理由阻止它在所有C库中通用,也没有理由阻止它有所不同,因此只要实现了printf()的标准定义即可。碰巧的是,不同的库开发人员已经阅读了标准的printf()定义,并提出了解析和处理格式字符串的不同方法。其中大多数都正确地做到了。
第二部分是将这些字符输出到stdout的位,这是区别所在。内核/操作系统负责输入/输出,并以特定方式完成。使Linux内核输出字符所需的源代码与使Windows输出字符所需的源代码非常不同。
在Linux上,通常使用glibc。这使用printf()做一些复杂的事情,将输出字符缓冲在管道中,直到输出换行符,然后才调用Linux系统调用以在屏幕上显示字符。这意味着来自单独线程的printf()调用被整齐地分开,每个线程都在各自的行上。但是,针对另一个Linux C库编译的相同程序源代码不一定会做相同的事情,从而导致来自不同线程的printf()输出变得混乱且不可读。
完全没有理由使用C编写包含printf()的库。只要遵守与C编译器所用函数调用约定相同的函数,就可以在汇编器中编写它(尽管有点生气!)。还是Ada(调用约定可能有点棘手...)。
答案 4 :(得分:0)
实现这些功能的源代码是否会不同
让我们尝试另一种观点:竞争。
不。 C规范不需要行业的竞争对手共享源代码来发布兼容的编译器-各种标准C库开发人员也不总是希望这样做。
C不需要“开源”。