是否为Linux和Windows以不同的方式实现了诸如printf()之类的功能

时间:2018-07-12 20:39:10

标签: c printf scanf stdio

我还是不太了解。例如,诸如printf()scanf()之类的标准C函数处理将数据发送到标准输出或从标准输入获取数据。实现这些功能的源代码会有所不同,这取决于我们是将它们用于Windows还是Linux?

我想快速的答案是“是”,但是它们真的必须有所不同吗?

我可能错了,但是我的猜测是实际的功能代码是相同的,但是最终被这些功能调用的OS的底层功能是不同的。因此,任何编译器都可以编译这些相同的C函数,但是正是这些链接赋予了我们所需的行为(这些函数依赖于在较低层上工作)?

5 个答案:

答案 0 :(得分:1)

  

实现这些功能的源代码是否会不同   取决于我们是在Windows还是Linux上使用它们?

可能是。在不同的Linux和不同的Windows程序上,它甚至可能有所不同。 C标准库有几种不同的实现可用于Linux,对于Windows甚至可能不止一种。不同的实现将具有不同的实现代码,否则律师会介入。

  

我的猜测是实际的功能代码是相同的,但是较低   最终被这些调用的操作系统的层功能   功能不同。所以任何编译器都可以编译这些相同的C   功能,但它是链接后的内容(这些功能是什么   取决于在较低的层上工作)是什么给了我们所需的   行为?

可以想象的是,标准库函数的编写方式可以将环境依赖关系抽象到一些较低的层,以便每个函数本身的相同源可以在多种环境中使用,并且具有某种环境-下面的特定兼容性层。由于GNU C库支持各种各样的环境,尽管Windows不在它支持的环境之内,它还是一般原则的一个示例。但是,即使那样,即使在链接阶段之前,环境区分也是有效的。不同的环境具有多种二进制格式。

但是,实际上,您不太可能看到针对Windows和Linux所描述的情况。

答案 1 :(得分:0)

是的,它们有不同的实现方式。

此外,您可能在同一OS上使用多种不同的实现。例如:

  • MinGW附带了自己的标准库实现,该实现与MSVC所使用的不同。
  • 甚至对于Linux,C库也有许多不同的实现:glibcmusldietlibc等。

很明显,这意味着社区中存在一些代码重复,但这有很多充分的理由:

    人们对如何实施和测试事物有不同的看法。仅此一项就足以“分叉”该项目。
  • 许可:实现对使用方式有一些限制,并且可能需要最终用户采取某些措施(GPL在某些情况下要求您共享代码)。并非每个人都能遵守这些要求。
  • 人们有不同的需求。有些环境是多线程的,有些则不是。 printf可能需要或可能不需要使用某些线程同步机制。有些人需要语言环境支持,有些则不需要。所有这些最终都会使代码膨胀,并不是每个人都愿意为不使用的东西付费。甚至strerror也是vastly different on different OSes
  • 上述同步机制通常是特定于OS的,并且以特定方式工作。在语言环境处理,信号处理和其他方面(包括实际的数据写入和读取)也可以这么说。
  • 某些实现添加了非标准扩展,可以使您的生活更轻松。并非所有这些在其他操作系统上都有意义。例如,glibc添加'e'模式说明符以打开带有O_CLOEXEC标志的文件。这对于Windows没有意义。
  • 许多复杂的事情无法在纯C语言中实现,并且需要某些特定于编译器的扩展。这可以将实现与有限数量的编译器联系起来。

最后,拥有许多C库比尝试创建一种“一刀切”的实现要简单得多。

答案 2 :(得分:0)

正如您所说,诸如printf之类的实现的高层部分,例如使用参数格式化字符串的代码,可以以跨平台的方式编写,并且可以在Linux和Windows之间共享。我不确定是否确实有C库可以实现此功能。

但是要与硬件交互或使用其他操作系统功能(例如,在printf写入控制台时),libc实现必须使用操作系统的接口:system calls。这些在Windows和类Unix之间是非常不同的,甚至在类Unix之间也有所不同(POSIX指定了很多,但是有特定于OS的扩展)。例如,您可以在这里找到LinuxWindows的系统调用表。

答案 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不需要“开源”。