20

On the Wikipedia page for Windows, it states the Windows is written in Assembly for the bootloader and task switcher, and C and C++ for kernel routines.

IIRC, you can call C++ functions from an extern "C"'d block. I can get using C for the kernel functions so pure C apps can use them (like printf and such), but if they can just be wrapped in an extern "C " block, then why code in C?

Cole Tobin
  • 1,440
  • 1
  • 15
  • 28
  • 10
    Have you seen the various "Why use C when there's C++?" questions here? This isn't necessarily a duplicate of any of them, but they *are* related. –  Dec 10 '12 at 17:56
  • 1
    "you can call C++ functions from an extern "C"'d block as C++" Do you mean you can call **C** functions...? – Code-Guru Dec 11 '12 at 04:36
  • @Code-Guru no, because the only difference between exported C and C++ functions is the name decoration and in C++, the addition of the `this` variable – Cole Tobin Dec 11 '12 at 04:56
  • 2
    Throw an exception in an ISR and see what happens – James Feb 06 '13 at 02:50
  • Yet another C vs. C++ question. – Machado Sep 30 '16 at 12:54

13 Answers13

31

It's mostly for historical reasons. Some parts of the windows kernel were originally written in C, because 1983, over three decades ago, when Windows 1.0 was unleashed, C++ was barely released. Now these C-libraries will stay there "forever", because Microsoft made backward-compatibility a selling point and rewriting a bug-compatible version of the C-parts in C++ requires an awful lot of effort for no effective benefit.

Andy
  • 10,238
  • 4
  • 25
  • 50
back2dos
  • 29,980
  • 3
  • 73
  • 114
  • +1, I guess that is the most realistic answer (besides the fact that there might be some Windows kernel devs who just don't like C++ or don't trust C++ compilers for that low-level stuff). Look, for example, here http://stackoverflow.com/questions/520068/why-is-the-linux-kernel-not-implemented-in-c, why the Linux kernel is written in C. – Doc Brown Dec 10 '12 at 18:07
  • @back2dos - While their C code won't be thrown away that doesn't mean it will be used or not updated. I guarantee you there is a least one method that does something that was originally written and contained within a C library that has been ported a C++ library in Windows 8 – Ramhound Dec 10 '12 at 18:09
  • 8
    I have a hard time believing that there is any Windows 1.0 code in any recent release of Windows. Windows ME was the last Windows release that wasn't based on the Windows NT code base. And even that has been largely replaced by the new RT kernel (which, as I understand it, doesn't promise very much in the way of backwards compatability). – TMN Dec 10 '12 at 18:23
  • @TMN: the argument is most probably correct either - I am pretty sure on the road from Win 1.0 to now there *were* a lot of libraries written in C which are still part of the current Win8 code base, and no one at MS sees any benefit to rewrite them in C++. – Doc Brown Dec 10 '12 at 21:37
  • 1
    There is hardly any code which talks to the Windows kernel anyway. Basically, only drivers do. Applications usually talk to the Win32 API, or possibly the POSIX API. – MSalters Dec 11 '12 at 12:33
  • Even with just the NT code base, C++ was still in a pretty woeful state (compared to C) back in 1992/1993. There will still be code from that in the current NT releases for the simple reason that it's working, tested, debugged code - and you don't rewrite such code. – Maximus Minimus Dec 11 '12 at 15:33
  • The Windows API is however written 100% in C, also for historical reasons. And even all new API functions released are in C. Even though Microsoft themselves encourage C++. They can't change it or there would be no more backwards compatibility. And there is no reason to change something for the sake of changing, either. –  Dec 11 '12 at 15:51
  • It should be noted that up until Windows 7, Windows only had a C-style API: Win32. Starting with Windows 8, this has been complemented by a COM-based (and therefore C++) API: WinRT. However, I cannot say if both of these outward-facing APIs are in turn based on a common internal kernel API, and if so, whether *that* was implemented in C. – stakx Jul 09 '14 at 09:44
  • @TMN: What the heck is "the RT kernel"? The kernel is the same old thing it always was, the NT kernel. – user541686 Jul 09 '14 at 10:14
  • @Mehrdad: It appears I overgeneralized, I was doing some heavy tablet development and may have misunderstood some of the evangelizing that MS doing at the time The [RT kernel](http://en.wikipedia.org/wiki/Windows_RT) was going to be the next big thing, along with Windows 8. The landscape has changed somewhat in the last year and a half. – TMN Jul 09 '14 at 16:03
  • +1 - Moreover, the argument stands not only for Windows but for all major OSes, including Linux and OS X. – mouviciel Aug 22 '14 at 07:48
24

As most people have pointed out, reasons are by far historical, but there is something else no one is mentioning and I believe it is the reason people still write C code for low-level.

C is a small language in the sense that the spec is (relatively) short. C++ is huge and that's an understatement. This may not matter that much to the programmer (although I think it does), but it is extremely important if you want to do formal verification. Furthermore there are established tools for C code analysis, that could help prevent bugs, etc.

And this is very important in embedded software, where the cost of a bug that is deployed is extremely high, relative to the rest of the industry (compare Web, where you can apply a patch immediately to all users). Not to mention mission-critical software and medical stuff.

There have been attempts to displace C from its dominant place in low-level programming with languages that are even better at this, like BitC, but they haven't been successful so far.

K.Steff
  • 4,475
  • 2
  • 31
  • 28
  • 4
    +1 For mentioning mission critical software in pure C (e.g. aeronautical software). However, in medical software C++ is also used (extensive testing is used instead of a formal verification, which would be extremely hard in C++). – Giorgio Dec 11 '12 at 06:18
  • 1
    Also, C has a rather successful safe subset MISRA-C. There are equivalents for C++, but they aren't industry de facto standard (yet). The trend in safety-critical programming is that libraries and compilers will also be forced to use a safe subset like MISRA. To re-write a MISRA-C++ compatible version of the whole C++ standard library will most likely be a nightmare. –  Dec 11 '12 at 15:55
  • 2
    @Lundin MISRA guidelines are not a safe subset - you still have raw pointers and most other features which make C unsafe - they mainly focus on not using or documenting implementation specific behaviour. – Pete Kirkham Feb 06 '13 at 08:59
  • @PeteKirkham MISRA-C will catch all the most classic pointer bugs and enforce static analysis. Industry safety standards (IEC 61508 et al) apparently approve MISRA-C as a safe subset of C. There aren't many other useful alternatives for mission-critical software, unless you pick SPARK Ada, a language that few know, with limited tool support. –  Feb 06 '13 at 13:02
  • 2
    This should have been selected as the best answer as it's correct. Others who suggest C is only used for historical reasons is hysterical in itself. – Rob Sep 30 '16 at 12:28
15
  1. The C runtime is much smaller.
  2. The translation of C++ into lower-level constructs is less transparent than in C. (See references and vtables, for two quick examples)
  3. C usually has a stable ABI. C++ usually does not. This means that at the bare minimum, the system call interface should be C style. In addition, if you want any sort of dynamic modules, having a consistent ABI helps greatly.
wnoise
  • 271
  • 2
  • 7
  • +1 for (2) and (3). I'm not convinced with (1). – Thomas Eding Dec 11 '12 at 08:47
  • 7
    @Thomas Eding: The C++ runtime consists of the C runtime, plus C++ features such as a exceptions, RTTI, and another memory allocator. YMMV as to whether that counts as _much_ larger. (And then there's the standard library...) – wnoise Dec 11 '12 at 23:26
  • Ah, I forgot about exceptions and new/delete pools. RTTI I never use though :D – Thomas Eding Dec 11 '12 at 23:32
11

The reasons aren't technical. A little bit of assembly is unavoidable, but they aren't forced to use the occasional C, they want to. My company uses its own proprietary kernel, written almost entirely in C++, but we don't need to support a C interface to the kernel like most everyone else, because our embedded kernel is monolithically compiled with our C++ applications. When you have a C interface, it's often easier to write the interface code in C, even though it's possible to use extern "C" to write it in C++.

Even we have a smattering of C files, mostly due to third-party code. Third-party low-level code is almost always provided in C, because it's much easier to incorporate C code into a C++ app than the other way around.

Karl Bielefeldt
  • 146,727
  • 38
  • 279
  • 479
6

Kernel developers are often the kind of people, who feel happier, when it is immediately evident from the source, what the code actually does.

C++ has many more features, which hide what the code does more than plain C code hides it: overloads, virtual methods, templates, references, throws... C++ also has vastly more syntax you have to master in order to even understand the C++ code using it.

I think power of C++ is very powerful tools to create libraries and frameworks, which then make application development a snap. Very often C++ application developer would be totally lost in the template-filled innards of a library, even when he is very competent at creating applications using that library. And writing a C++ library right is a very challenging programming task, and only done in order to provide a great framework for the benefit of application developer. C++ libraries are not internally simple, they are (or can be...) just powerful yet simple from application programmers point of view.

But kernel API can not be a C++ API, it must be a language-agnostic API, so most of the nice things in C++ would not be directly usable at that interface. Furthermore, kernel is not really divided into "library" and "application" parts developed independently, with more effort logically going to one library, to make creation of a mass of applications easy.

Also, security and stability is more critical inside a kernel, and virtual methods are much more dynamic and therefore much harder to isolate and verify, than plain callbacks or other C-like mechanisms.

In short, while you could of course write any C program including a kernel as C++, most of the power of C++ is not well used in kernel. And many would argue, that programming tools should prevent you from doing things you should not do. C++ would not.

hyde
  • 3,744
  • 4
  • 25
  • 35
  • +1. As a kernel developer my "rule of thumb" is that if you can't estimate "cache lines touched" easily then the language you're using is doing more harm than good. – Brendan Sep 30 '16 at 21:58
  • Clarification: For kernels you have to assume that CPU spends most its time in user-space and kernel code is used sporadically (e.g. when user-space calls kernel API or an interrupt occurs); which means that you have to assume "cold cache". For modern CPUs (where RAM is slow relative to CPU speed) cache and TLB misses are expensive, so (combined with the "cold cache" expectation) the "cache lines touched" metric becomes an extremely important indicator for performance and/or scalability. – Brendan Sep 30 '16 at 22:07
5

Bjarne Stroustrup, in an interview in July 1999:

None of these languages was radically different or dramatically better than other contemporary languages. They were, however, good enough and the beneficiaries of luck and social factors

gnat
  • 21,442
  • 29
  • 112
  • 288
david
  • 275
  • 1
  • 3
3

C is a very low-level language, by its design. It's one step away from assembler; knowing the chipset you're targeting, you could, with a little knowledge, manually "compile" C into ASM. This kind of "close-to-the-metal" language is key for high levels of optimization (for performance, memory-efficiency, etc). However, because it's this close to the metal, you don't get much for free with this language; it is a procedural, non-object-oriented language, and thus to work with such constructs involves a lot of boilerplate code to create and consume multi-value constructs in memory.

C++ is "C one better", adding a number of ease-of-use features such as dynamic memory allocation, built-in structure marshalling, a large library of predefined code, etc, at the expense of some efficiency losses (still much better than managed-runtime environments). For the average coder, the advantages far outweigh the disadvantages in areas of the codebase that don't need anal-retentive control of memory allocation etc.

The combination of the two is a pretty traditional one; you use C to write the most performance-critical, memory-efficient areas of the codebase, which you can then work with in a more abstracted fashion via method calls from C++ code, which can be more elegantly organized and designed than the uber-performant, uber-oogly optimized C code.

KeithS
  • 21,994
  • 6
  • 52
  • 79
  • 2
    Regarding efficiency, I'll repeat myself: (1) The C++ folks will tell you that's bullshit. (2) I'm saying I see no reason this ought to be the case, and would like concrete examples. Not examples of how it's easy to write less efficient code, but examples of how being as efficient as C requires undue ugliness. –  Dec 10 '12 at 18:18
  • 3
    Define "ugly"; I code in C# for a living, and whenever I see C++ code examples in StackOverflow I cringe at how much cruft is considered normal in the day-in-day-out usage of the language. When I coded in C++ way back when, I often saw C code and cringed; hand-packing structure types, execution pointer calculations for manual jumps, embedded ASM... yuck. Some people bemoan the loss of low-level knowledge among Java/.NET programmers; I consider it a huge boon to productivity. – KeithS Dec 10 '12 at 18:27
  • 1
    You didn't answer my question ;) By "ugly" I mean "ugly by C++ gurus' standards". In other words, examples where one cannot use "modern C++" and be as efficient as C. –  Dec 10 '12 at 18:30
  • Obviously as a C# programmer by trade I've fallen out of study and practice with C++, so I can't give a concrete example. Suffice to say, it is a fundamental principle that the more abstracted you get, the more code is between you and the hardware that you don't have control over. Relatively speaking, C++ doesn't lose as much to C as a managed-memory runtime loses to a native runtime, but a C++ runtime still gives the coder things they don't have to worry about vs C. The developers of the compilers/libraries *do* have to worry about those things, and usually cannot afford to be optimistic. – KeithS Dec 10 '12 at 18:37
  • 1
    I hoped that you'd have specific abstractions in mind. In general, almost all abstractions provided by C++ can be eliminated at compile time. Examples include overloading, generic functions/types via templates, template metaprogramming, lambdas, objects and (non-`virtual`) member functions, and iterators. The only exceptions I know of are exceptions (though most compilers implement them in a way that adds zero runtime overhead when no exceptions are thrown) and `virtual` (obviously). Both are discouraged in communities concerned with performance, and AFAIK not really vital in "modern C++". –  Dec 10 '12 at 18:59
  • 1
    @delnan : It's hard to disagree with you, I really wish you were correct. I have worked with average programmers hacking away at C++ and doing it badly. Bad C written by average programmers is easy and common, but still relatively efficient. Bad C++ written by the same guys is easier and more common, and significantly less efficient. Unfortunately you have to compare C++ written by Average programmers to C written by Average programmers -and IMHO, based on experience over theory, C++ looses. – mattnz Dec 10 '12 at 20:25
  • 2
    That may be true (I honestly don't know). For kernel development (and a few other fields), we're not talking about average programmers though. –  Dec 10 '12 at 20:42
  • @mattnz: You are right that C is a much easier programming language to master than C++. Even expert C++ programmers may not know about corner cases related to lesser-known features of the language that can make their application crash if not used correctly (I speak from personal experience). So I find it understandable that C may be preferred in some applications. – Giorgio Dec 11 '12 at 06:24
  • +1: I can usually beat the compiler in performance when it comes to writing assembly and it is a LOT easier to predict how the compiler will translate C into assembly compared to C++. – Leo Dec 11 '12 at 12:35
  • 1
    I think the author of this answer forgets that code that matches the C standard compiled by a C++ compiler is actually just C++ code that conforms to the C standard. Honestly C++ is no more high level then C is. The major differences between the languages are the compiler and syntax sugar. C could be extended to do pretty much everything C++ does, and actually C has been extended a good deal, but those extensions come at the cost of portability and thus are used less. – Ramhound Dec 11 '12 at 14:44
  • 3
    People forget that C -> C++ is a continuum. Too often, these arguments are comparing good, modern C++ with C. You can take a C program and get it compiling with a C++ compiler in a relatively short time and it will run exactly as fast. If a modern C++ feature is "too slow", don't use it. That can even include things like `iostream`. "Too slow" is never a good excuse to use C over C++. – Gort the Robot Dec 13 '12 at 18:22
1

It could be that with C you spend most of your time thinking about the problem at hand and how to code the solution. In C++ you end up thinking about C++ and its myriad of features, functions and obscure syntax.

Also in many C++ shops your code get monitored by the "fashion police" who are enthralled by the latest set of design patterns, or, the latest unintelligible pronouncements of the great god Stroustrup. Pretty code becomes more valued than working code, finding a use for the latest set of Boost templates is admired more than finding a working solution for the business.

My experience is that for all the clever features and OO purity of C++, coding in plain C gets the job done quicker and more effectively.

James Anderson
  • 18,049
  • 1
  • 42
  • 72
0

It's possible that the C parts are not nicely portable to the C++ compiler that is used for the C++ parts. Maybe the C code is chummy with the C compiler in ways that break with the C++ compiler.

If you have a quality C++ compiler, there is almost no reason to mix C and C++ in a project. Almost.

The one reason would be that your project shares C code with other projects, the code does not compile as C++, and you don't want to maintain a C++ fork of that that code.

Kaz
  • 3,572
  • 1
  • 19
  • 30
-1

I think you have it backwards -- the extern "C" block ensures that the C calling conventions are used for all functions within the block. So you can call pure C functions from C++, not C++ functions from C. Regardless, I imagine that the reason people use both C and C++ is because a lot of low-level libraries are written using C, and it's easier to use something that already exists (and is presumably debugged and optimized) than writing your own. OTOH, C++ offers a lot of nice high-level features that people would rather work with, so they use that for the rest.

TMN
  • 11,313
  • 1
  • 21
  • 31
-2

There are various level of embedded platforms using C as programming language ( of course it is your freedom to use assembly language at any time )

For 'Level' I am talking about the Internal SRAM and ROM resource level for a system.

These platforms sometimes are resource constrained ( e.g. some 8051 platforms only have 128 bytes of User SRAM ).

It is meaningless to support dynamic memory allocation with such a small amount for RAM. (new/delete) or even malloc in C.

One of the main improvement from C to C++ is Object-oriented paradigm. C++ is suitable in software with larger memory footprint

but not in embedded firmware that have its size limitation up to 32KB. (e.g. in a 16-bit MCU plaform )

There is no need to have a C++ compiler which is generally more complicated than C compiler. ( at least SDK providers won't bother to do this ).

In fact I can hardly find a C++ compiler over an 32-bit ARM7 platform.

It just doesn't worth the complexity

In Some 8051(8 bit) : 1MB ROM, 128B RAM

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

ST Microelectronics ARM 32-bit Cortex™-M3 CPU Core ( STM32F103T4 ) : 16 or 32 Kbytes of Flash memory 6 or 10 Kbytes of SRAM

ansonchau
  • 1
  • 1
-4

Because C is arguably a better language than C++. And because some of the code was written before C++ became popular and people haven't had a reason to replace it.

And because C++ has lots of features that can break your code if you're not careful when using it in a kernel.

Minthos
  • 240
  • 1
  • 4
  • C++ expects dynamic libraries? And what's dynamic memory? –  Dec 10 '12 at 17:55
  • Dynamically allocated memory, i.e. a heap. C++ itself doesn't expect libraries, but to use C++ efficiently the programmers who use it expects to have dynamic libraries available. – Minthos Dec 10 '12 at 17:55
  • 4
    -1 for `[stuff] that C++ expects`. Why does C++ use more heap than C? Why does C++ require more dlls than C? Simply NOT TRUE – Thomas Eding Dec 10 '12 at 17:56
  • And how does C++ expect that? –  Dec 10 '12 at 17:56
  • Yes you can use C++ without a heap, but then you lose most of the features that differentiate C++ from C. So you might as well write in C. – Minthos Dec 10 '12 at 17:58
  • 1
    Correction: You lose the libraries that are written in C++. So its back to square 1 if you are using C++ or C. Why limit yourself to C functionality if you can use templates, classes, destructors, const, and all sorts of other goodness. – Thomas Eding Dec 10 '12 at 17:59
  • 6
    What? Templates, exceptions, objects (including constructors, destructors, overloaded operators, now move construction, and - practically? - everything else), etc. work just fine regardless where the memory's from (stack, static memory, your custom pool, or whatever). The standard containers use heap allocation by default, but their allocators can be customized and kernel guys write their own collections and memory management anyway. -1 –  Dec 10 '12 at 18:00
  • All right, edited my answer. – Minthos Dec 10 '12 at 18:04
  • I still don't see why you even *mention* the heap. As laid out above, you can (and many people do) completely control where your C++ objects go. A kernel developer avoiding `new` shouldn't have a harder time than a game developer avoiding `new`, and I happen to know that the latter get along just fine with C++. The rest of the sentence doesn't make much sense either: Why does a kernel have to function without C++ libraries (in general; obviously most code in both C and C++ is unsuitable for kernels)? –  Dec 10 '12 at 18:07
  • 2
    FYI: I removed my downvote because I don't think your answer is actively harmful by now, but I don't consider it particular useful or insightful either. –  Dec 10 '12 at 18:19
  • @Minthos: I have added a few words to make your answer a little bit more constructive. If you don't like my suggestion, please remove my edit. – Doc Brown Dec 11 '12 at 09:05
  • Why would M$ think C is better when they essentially drop C from M$VS. they barely even support c99 and have instead (so I've heard) C++11 and C#5 – Cole Tobin Dec 13 '12 at 16:51
  • You're right. As a whole they clearly don't, but there are bound to be some kernel programmers there who do. – Minthos Dec 13 '12 at 17:13
-4

I see a couple of possible reasons:

  • C is a little bit more efficient if compared to the C++ equivalent.
  • Some libraries they use are written in C.
  • They use some parts of Linux kernel, which is written in C.

Edited: As it turns out, third argument is not true (see comments).

Pijusn
  • 987
  • 1
  • 10
  • 16
  • 5
    (1) The C++ folks would beg to differ. And objectively I see no reason this should be the case. (2) C++ can call into C code just fine (that's the whole point of backwards compatibility and `extern "C"`). –  Dec 10 '12 at 17:54
  • 1
    If MS uses some parts of the Linux kernel, and the Linux kernel is GPL, wouldn't that mean that Windows would also have to be GPL? – TomJ Dec 10 '12 at 17:55
  • 1
    @TomJ actually that's why they were forced to donated a couple thousands of lines to Linux as well. + Why do you think they support Linux development? – Pijusn Dec 10 '12 at 17:57
  • 2
    @Pius His point is (and he's right AFAIK), if there was GPL's code linked into the Windows kernel, the whole kernel would have to be GPL'd (provided there isn't a separate agreement with the copyright holders). –  Dec 10 '12 at 17:58
  • @delnan, not sure about the details. I'm not a lawyer so I cannot comment on that. But there was a small scandal a couple years ago about this. Not sure but I think I might have been the networking module all the crazy stuff was about. – Pijusn Dec 10 '12 at 18:00
  • Ok, my bad if so :) – Pijusn Dec 10 '12 at 18:00
  • I thought it was some BSD code, either for networking or some userland network-related programs. – alroc Dec 10 '12 at 18:09
  • Before XP or so they used the BSD network stack for TCP/IP things, but that's gone and not linux and not GPL :) – johannes Dec 10 '12 at 23:44