为什么操作系统会在C和C ++中做底层工作?为什么不只是C ++?


20

WindowsWikipedia页面上,它指出Windows是用Assembly语言编写的,用于引导加载程序和任务切换器,以及C C ++语言的内核例程。

IIRC,您可以从extern "C"'d块调用C ++函数。我可以将C用于内核函数,这样纯C应用程序就可以使用它们(诸如此类printf),但是如果它们只能包装在一个extern "C "块中,那么为什么要用C语言编写代码?


10
您是否看到过各种“为什么有C ++时为什么使用C”?这里有问题吗?这不一定是其中任何一个的重复,但是它们相关的。

1
“您可以从外部“ C”块中调用C ++函数作为C ++”“您是说您可以调用C函数...?
Code-Guru

@ Code-Guru不,因为导出的C和C ++函数之间的唯一区别是名称修饰,而在C ++中,添加了this变量
Cole Johnson

2
在ISR中引发异常,看看会发生什么
詹姆斯

还有另一个C vs. C ++问题。
马查多

Answers:


31

这主要是出于历史原因。Windows内核的某些部分最初是用C编写的,因为1983年,即三十多年前,当Windows 1.0发布时,C ++才刚刚发布。现在,这些C库将“永远存在”,因为Microsoft将向后兼容性作为卖点,而用C ++重写与C部分兼容的bug版本则需要付出大量的努力,而没有任何有效的收益。


+1,我想这是最现实的答案(除了可能有些Windows内核开发人员不喜欢C ++或不信任C ++编译器用于这些低级内容的事实)。你看,例如,这里stackoverflow.com/questions/520068/...,为什么Linux内核是用C写
布朗博士

@ back2dos-尽管它们的C代码不会被丢弃,但这并不意味着它将被使用或未更新。我向您保证,至少有一种方法可以完成最初编写并包含在已移植到Windows 8中的C ++库的C库中的
某些操作

8
我很难相信最新的Windows版本中都有Windows 1.0代码。Windows ME是最后一个不基于Windows NT代码库的Windows版本。甚至它已经在很大程度上被新的RT内核所取代(据我所知,它在向后兼容性方面没有太大的保证)。
TMN 2012年

@TMN:该论点很可能是正确的-从Win 1.0到现在,我可以肯定的是,有很多用C编写的库仍然是当前Win8代码库的一部分,而MS的人都看不到用C ++重写它们的好处。
布朗

1
无论如何,几乎没有任何代码可以与Windows内核对话。基本上,只有驱动程序可以。应用程序通常会与Win32 API或POSIX API进行通信。
MSalters

24

正如大多数人所指出的,到目前为止,原因是有历史的,但是没有人提及,我相信这就是人们仍然为底层编写C代码的原因。

就规范而言(相对)简短而言,C是一门小语言。C ++非常庞大,这是一种轻描淡写的说法。对于程序员来说,这可能无关紧要(尽管我认为确实如此),但是如果您要进行形式验证,则这非常重要。此外,已经建立了用于C代码分析的工具,可以帮助防止错误等。

对于嵌入式软件而言,这是非常重要的,相对于其他行业,嵌入式软件中部署错误的成本非常高(比较Web,您可以在其中立即将补丁应用于所有用户)。更不用说关键任务软件和医疗产品了。

曾有人试图用低级编程(例如BitC)将C从其在低级编程中的主导地位中移开,但到目前为止还没有成功。


4
+1关于提及纯C语言中的关键任务软件(例如航空软件)。但是,在医疗软件中也使用C ++(使用广泛的测试代替形式验证,这在C ++中将非常困难)。
乔治

1
而且,C具有相当成功的安全子集MISRA-C。有C ++的等效项,但还不是行业实际标准(尚未)。安全关键型编程的趋势是,库和编译器也将被迫使用像MISRA这样的安全子集。重新编写整个C ++标准库的MISRA-C ++兼容版本很可能是一场噩梦。

2
@Lundin MISRA准则不是一个安全的子集-您仍然拥有原始指针和大多数其他使C不安全的功能-它们主要集中在不使用或记录实现特定的行为。
皮特·柯坎

@PeteKirkham MISRA-C将捕获所有最经典的指针错误并强制进行静态分析。行业安全标准(IEC 61508等)显然批准MISRA-C作为C的安全子集。除非您选择SPARK Ada(一种鲜为人知的语言,并且使用有限的工具),否则任务关键型软件没有很多其他有用的替代方法。支持。

2
因为它是正确的,所以应该选择它作为最佳答案。其他建议仅出于历史原因使用C的人本身就是歇斯底里的。
罗布

15
  1. C运行时要小得多。
  2. 与C语言相比,将C ++转换为低级结构的透明性较差。(有关两个快速示例,请参见参考资料和vtables)
  3. C通常具有稳定的ABI。C ++通常不会。这意味着系统调用接口至少应为C样式。另外,如果您需要任何种类的动态模块,那么拥有一致的ABI将会有很大的帮助。

为(2)和(3)+1。我不相信(1)。
Thomas Eding

7
@Thomas Eding:C ++运行时包含C运行时,以及C ++功能(例如,异常,RTTI和另一个内存分配器)。YMMV关于它是否重要得多。(然后是标准库...)
wnoise 2012年

啊,我忘记了异常和新池/删除池。RTTI我从未使用过:D
Thomas Eding

11

原因不是技术原因。组装一点点是不可避免的,但它们不是强制使用,偶尔C,他们希望到。我公司使用自己的专有内核,几乎完全用C ++编写,但是我们不需要像大多数其他大多数人一样支持到内核的C接口,因为嵌入式内核是用C ++应用程序整体编译的。使用C接口时,即使可以extern "C"C ++ 编写接口代码,通常也更容易用C编写接口代码。

即使是我们也有一些C文件,这主要是由于第三方代码所致。第三方低级代码几乎总是用C提供的,因为将C代码合并到C ++应用程序中比使用其他方法容易得多。


6

内核开发人员通常是那种会感到更快乐的人,当从源头上立即看到代码实际上是做什么的时候。

C ++具有更多功能,这些功能比普通的C代码更能隐藏代码:重载,虚方法,模板,引用,抛出... C ++还必须掌握更多的语法才能理解C ++。使用它的代码。

我认为C ++的强大功能非常强大,可以创建库和框架,从而使应用程序开发变得轻而易举。即使C ++应用程序开发人员非常有能力使用该库创建应用程序,但通常情况下,他们都会完全迷失在该库的模板填充内部。正确地编写C ++库权限是一项非常具有挑战性的编程任务,仅是为了为应用程序开发人员的利益提供良好的框架而完成。C ++库在内部并不是简单的,从应用程序程序员的角度来看,它们是(或可以...)功能强大而又简单。

但是内核API不能是C ++ API,它必须是与语言无关的API,因此C ++中的大多数优点都不能在该接口上直接使用。此外,内核并没有真正分为独立开发的“库”和“应用程序”部分,逻辑上需要花费更多的精力到一个库上,以简化大量应用程序的创建。

而且,与纯回调或其他类似C的机制相比,内核内部的安全性和稳定性更为关键,虚拟方法更具动态性,因此更难隔离和验证。

简而言之,尽管您当然可以将包括内核在内的任何C程序编写为C ++,但是C ++的大多数功能在内核中并未得到很好的利用。许多人会认为,编程工具应阻止您执行不应执行的操作。C ++不会。


+1。作为内核开发人员,我的“经验法则”是,如果您无法轻松地估计“触及的缓存行”,那么使用的语言弊大于利。
布伦丹

说明:对于内核,您必须假定CPU将其大部分时间花费在用户空间上,并且偶尔使用内核代码(例如,当用户空间调用内核API或发生中断时);这意味着您必须假设“冷缓存”。对于现代CPU(RAM相对于CPU速度而言较慢),高速缓存和TLB未命中的代价很高,因此(与“冷高速缓存”期望值结合)“高速缓存行”指标成为性能和/或可伸缩性的极其重要的指标。
布伦丹

5

Bjarne Stroustrup 在1999年7月的一次采访中

这些语言都没有一个比其他当代语言有根本不同或有显着提高。但是,他们足够好,是运气和社会因素的受益者


2
欢迎大卫。引用或引用时,最好提供参考(补充!)
Andrew

3

从设计的角度来看,C是一种非常底层的语言。距汇编程序仅一步之遥;知道了您要定位的芯片组后,您只需一点知识就可以将C手动“编译”为ASM。这种“最接近金属”的语言对于高水平的优化(性能,内存效率等)至关重要。但是,因为它离金属很近,所以用这种语言您不会免费得到很多。它是一种过程性的,非面向对象的语言,因此使用此类构造涉及大量样板代码来创建和使用内存中的多值构造。

C ++是“更好的C语言”,它添加了许多易于使用的功能,例如动态内存分配,内置结构编组,大量预定义代码库等,但以牺牲一些效率为代价(仍然更好)比托管运行时环境)。对于普通编码器而言,在不需要对内存分配进行肛门保持控制的代码库领域中,其优点远胜于缺点。

两者的结合是很传统的。您可以使用C编写代码库中对性能最关键,内存效率最高的区域,然后可以通过C ++代码中的方法调用以更加抽象的方式使用该区域,该代码可以比超级性能更好地组织和设计。 ,超级优化的C代码。


2
关于效率,我将重复自己一遍:(1)C ++人士会告诉你这是胡扯。(2)我的意思是我认为没有任何理由应该这样做,而是想举一些具体的例子。不是编写效率较低的代码很容易的示例,而是有关C效率如何的示例,这些示例需要适当的丑陋处理。

3
定义“丑陋”;我用C#编写代码谋生,每当我在StackOverflow中看到C ++代码示例时,我都会畏缩在该语言的日常使用中多少被认为是正常的。当我以C ++的方式编写代码的时候,我经常看到C代码并感到欣慰。手动打包结构类型,用于手动跳转的执行指针计算,嵌入式ASM ...糟糕。有些人为Java / .NET程序员中的低级知识丧失而感到be惜。我认为这极大地促进了生产力。
KeithS 2012年

1
您没有回答我的问题;)“丑陋”是指“按照C ++专家的标准是丑陋的”。换句话说,实施例,其中一个不能使用的“现代C ++”和是一样有效C.

2
可能是正确的(老实说我不知道​​)。对于内核开发(以及其他一些领域),我们并不是在谈论普通程序员。

3
人们忘记了C-> C ++是一个连续体。这些参数常常将好的现代C ++与C进行比较。您可以选择一个C程序,并在相对较短的时间内使用C ++编译器对其进行编译,并且它的运行速度也将与之相当。如果现代C ++功能“太慢”,请不要使用它。甚至可以包括诸如此类的内容iostream。“太慢”绝不是在C ++上使用C的好借口。
砸碎了机器人

1

可能是因为使用C,您将大部分时间花在思考手头的问题以及如何编码解决方案上。在C ++中,您最终会想到C ++及其众多的功能,函数和晦涩的语法。

同样,在许多C ++商店中,您的代码也受到“时尚警察”的监视,他们被最新的设计模式集或伟大的上帝Stroustrup的最新的令人费解的声明所吸引。漂亮的代码变得比工作代码更有价值,与为业务找到可行的解决方案相比,钦佩使用最新的Boost模板集更令人钦佩。

我的经验是,对于C ++的所有聪明功能和OO纯度,纯C语言编码可更快,更有效地完成工作。


0

C部分可能无法很好地移植到用于C ++部分的C ++编译器中。也许C代码在C编译器方面有点笨拙,而与C ++编译器的关系却不那么理想。

如果您有高质量的C ++编译器,几乎没有理由在项目中混合使用C和C ++。几乎。

一个原因是您的项目与其他项目共享C代码,该代码无法作为C ++编译,并且您不想维护该代码的C ++分支。


-1

我认为您倒向了它-该extern "C"块确保将C调用约定用于该块内的所有函数。因此,您可以从C ++调用纯C函数,而不是从C调用C ++函数。无论如何,我想人们同时使用C和C ++的原因是因为许多低级库都是使用C编写的,因此使用比编写自己的脚本已经存在(可能已调试和优化)。OTOH,C ++提供了许多人们希望使用的出色的高级功能,因此他们将其用于其余部分。


-2

有多种级别的嵌入式平台使用C作为编程语言(当然,您可以随时使用汇编语言)

对于“级别”,我说的是系统的内部SRAM和ROM资源级别。

这些平台有时受到资源限制(例如,某些8051平台仅具有128字节的User SRAM)。

以如此少量的RAM支持动态内存分配是没有意义的。(新建/删除),甚至在C中使用malloc。

从C到C ++的主要改进之一是面向对象的范例。C ++适用于具有更大内存占用量的软件

但不能在大小上限为32KB的嵌入式固件中使用。(例如,在16位MCU平台中)

不需要C ++编译器,它通常比C编译器复杂。(至少SDK提供程序不会这样做)。

实际上,我几乎无法在32位ARM7平台上找到C ++编译器。

只是不值得复杂

在某些8051(8位)中:1MB ROM,128B RAM

TI MSP430(16位):32KB ROM,4KB RAM

ST Microelectronics ARM 32位Cortex™-M3 CPU内核(STM32F103T4):16或32 KB闪存6或10 KB SRAM


2
这对于此处已经发布的其他答案没有什么新意。
马丁·彼得

用于ARM的32位C ++编译器?如果需要,可以在进行一些修改后从源代码自己编译LLVM,以获得适用于iOS的C ++编译器。
科尔·约翰逊

-4

我看到一些可能的原因:

  • 与C ++相比,C的效率更高。
  • 他们使用的某些库是用C编写的。
  • 他们使用Linux内核的某些部分,这些部分是用C编写的。

编辑:事实证明,第三个参数不正确(请参阅注释)。


5
(1)C ++人士可能会有所不同。客观上,我认为没有理由是这种情况。(2)C ++可以很好地调用C代码(这是向后兼容性and的全部要点extern "C")。

1
如果MS使用Linux内核的某些部分,并且Linux内核是GPL,这是否意味着Windows也必须是GPL?
TomJ 2012年

1
@TomJ实际上这就是为什么他们也被迫向Linux捐赠了数千行。+为什么您认为他们支持Linux开发?
Pijusn 2012年

2
@Pius他的意思是(他是正确的AFAIK),如果Windows内核中链接了GPL的代码,则整个内核都必须是GPL(前提是没有与版权所有者达成单独协议)。

@delnan,不确定细节。我不是律师,所以我无法对此发表评论。但是几年前有一个小丑闻。不确定,但我想我可能已经成为所有疯狂的东西都在使用的网络模块。
Pijusn 2012年

-4

因为可以说C是比C ++更好的语言。而且由于某些代码是在C ++流行之前编写的,因此人们没有理由替换它。

而且由于C ++具有许多功能,如果您不小心在内核中使用它,可能会破坏您的代码。


C ++需要动态库吗?什么是动态内存?

4
-1表示[stuff] that C++ expects。为什么C ++比C使用更多的堆?为什么C ++比C需要更多的dll?并非完全正确
Thomas Eding

1
更正:您会丢失用C ++编写的库。因此,如果您使用的是C ++或C,则返回到平方1。如果可以使用模板,类,析构函数,const和其他各种优点,为什么还要限制自己使用C功能。
Thomas Eding

6
什么?模板,异常,对象(包括构造函数,析构函数,重载运算符,现在移动构造,以及-实际上是-其他所有东西)等都可以正常工作,无论内存来自何处(堆栈,静态内存,您的自定义池等) 。默认情况下,标准容器使用堆分配,但是可以对它们的分配器进行自定义,并且内核人员无论如何都要编写自己的集合和内存管理。-1

2
仅供参考:我删除了我的反对意见,因为我认为您的回答目前尚无积极意义,但我也不认为它特别有用或有见地。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.