73

C is one of the most widely-used languages in the world. It accounts for a huge proportion of existing code and continues to be used for a vast amount of new code. It's beloved by its users, it's so widely ported that being able to run C is to many the informal definition of a platform, and is praised by its fans for being a "small" language with a relatively clean set of features.

So where are all the compilers?

On the desktop, there are (realistically) two: GCC and Clang. Thinking about it for a few seconds you'll probably remember Intel exists as well. There are a handful of others, far too obscure for the average person to name and almost universally not bothering to support a recent language version (or often even a well-defined language subset, just "a subset"). Half of the members of this list are historical footnotes; most of the rest are very specialized and still don't actually implement the full language. Very few actually seem to be open-source.

Scheme and Forth - other small languages that are beloved by their fans for it - probably have more compilers than actual users. Even something like SML has more "serious" implementations to choose between than C. Whereas the announcement of a new (unfinished) C compiler aiming at verification actually sees some pretty negative responses, and veteran implementations struggle to get enough contributors to even catch up to C99.

Why? Is implementing C so hard? It isn't C++. Do users simply have a very skewed idea about what complexity group it falls in (i.e. that it actually is closer to C++ than Scheme)?

  • 61
    MSVC still counts, as a C89 compiler at least. Probably more popular than Intel even. – Rufflewind Feb 19 '15 at 2:50
  • 22
    Wikipedia lists quite a few C compilers. They get very common when you find yourself in the embedded realm. – user40980 Feb 19 '15 at 2:51
  • 112
    how many compilers do you need to compile your C code? – Bryan Chen Feb 19 '15 at 2:57
  • 76
    The question is based upon a false premise. Analog Devices, armcc, Bruce's C Compiler, the Bare-C Cross Compiler, the Borland compiler, the clang compiler, the Cosmic C compiler, the CodeWarrior compiler, the dokto compiler, the Ericsson compiler, and I'm not even out of the first five letters of the alphabet yet. There is an insanely large number of C compilers. The question is "why are there so few C compilers, if we don't count these several dozens as real C compilers?" You have defined away the vast majority of C compilers as not interesting, which is why there are not very many of them. – Eric Lippert Feb 19 '15 at 18:45
  • 19
    "Why" questions are bad questions for this site at the best of times, and "why not?" questions are worse. If I were to meet you at a party and ask "so, why don't you race sailboats?" I think you'd rightly find it to be an odd question. You don't need to provide a justification for NOT engaging in a technically difficult, physically risky and very expensive hobby. Writing any non-trivial piece of software is expensive, difficult and risky and therefore requires an enormous motivator. A better question would be "why are there so many C compilers?" It is surprising that there is more than one. – Eric Lippert Feb 19 '15 at 18:53
153

Today, you need a real C compiler to be an optimizing compiler, notably because C is no longer a language close to the hardware, because current processors are incredibly complex (out-of-order, pipelined, superscalar, with complex caches & TLB, hence needing instruction scheduling, etc...). Today's x86 processors are not like i386 processors of the previous century, even if both are able to run the same machine code. See the C is not a low level language (Your computer is not a fast PDP-11) paper by David Chisnall.

Few people are using naive non-optimizing C compilers like tinycc or nwcc, since they produce code which is several times slower than what optimizing compilers can give.

Coding an optimizing compiler is difficult. Notice that both GCC and Clang are optimizing some "source language-neutral" code representation (Gimple for GCC, LLVM for Clang). The complexity of a good C compiler is not in the parsing phase!

In particular, making a C++ compiler is not much harder than making a C compiler: parsing C++ and transforming it into some internal code representation is complex (because the C++ specification is complex), but is well understood, but the optimization parts are even more complex (inside GCC: the middle-end optimizations, source-language and target-processor neutral, form the majority of the compiler, with the rest being balanced between front-ends for several languages and back-ends for several processors). Hence most optimizing C compilers are also able to compile some other languages, like C++, Fortran, D, ... The C++ specific parts of GCC are about 20% of the compiler...

Also, C (or C++) is so widely used that people expect their code to be compilable even when it does not exactly follow the official standards, which do not define precisely enough the semantics of the language (so each compiler may have its own interpretation of it). Look also into the CompCert proved C compiler, and the Frama-C static analyzer, which care about more formal semantics of C.

And optimizations are a long-tail phenomenon: implementing a few simple optimizations is easy, but they won't make a compiler competitive! You need to implement a lot of different optimizations, and to organize and combine them cleverly, to get a real-world compiler that is competitive. In other words, a real-world optimizing compiler has to be a complex piece of software. BTW, both GCC and Clang/LLVM have several internal specialized C/C++ code generators. And both are huge beasts (several millions of source lines of code, with a growth rate of several percent each year) with a large developer community (a few hundred persons, working mostly full-time, or at least half-time).

Notice that there is no (to the best of my knowledge) multi-threaded C compiler, even if some parts of a compiler could be run in parallel (e.g. intra-procedural optimization, register allocation, instruction scheduling... ). And parallel build with make -j is not always enough (especially with LTO).

Also, it is difficult to get funded on coding a C compiler from scratch, and such an effort needs to last several years. Finally, most C or C++ compilers are free software today (there is no longer a market for new proprietary compilers sold by startups) or at least are monopolistic commodities (like Microsoft Visual C++), and being a free software is nearly required for compilers (because they need contributions from many different organizations).

I'd be delighted to get funding to work on a C compiler from scratch as free software, but I am not naive enough to believe that is possible today!

  • 14
    (there is no more a market for proprietary compilers Tell that to the Visual Studio team... – Mason Wheeler Feb 19 '15 at 10:15
  • 18
    Microsoft has a monopoly. I meant that small companies developing new C compilers won't sell a lot of them. Can you name a recent proprietary competitor to MSVC? – Basile Starynkevitch Feb 19 '15 at 10:23
  • 12
    There are many proprietary compilers in the HPC world. PGCC, NAG, and ICC are the most widely used. – Davidmh Feb 19 '15 at 13:09
  • 37
    @MasonWheeler: VS is given away for free nowadays (as in beer). The non-free versions add tooling, but the C compiler in VS2013 is the same in all versions. There just isn't a market, not even for them. – MSalters Feb 19 '15 at 16:06
  • 3
    But both GCC & LLVM are operating on much lower representations, and they optimize likewise C++ & C (& Ada & Fortran, for GCC) code. I would on the contrary say that C++ requires more optimization (notably when compiling code using its STL) than C! – Basile Starynkevitch Feb 20 '15 at 12:17
70

I would like to contest your underlying assumption that there are only a small number of C implementations.

I don't even know C, I don't use C, I am not a member of the C community, and yet, even I know far more than the few compilers you mentioned.

First and foremost, there is the compiler which probably completely dwarfs both GCC and Clang on the desktop: Microsoft Visual C. Despite the inroads that both OSX and Linux have been making on the desktop, and the marketshare that iOS and Android have "stolen" away from former traditional desktop users, Windows is still the dominant desktop OS, and the majority of Windows desktop C programs are probably compiled using Microsoft tools.

Traditionally, every OS vendor and every chip vendor had their own compilers. Microsoft, as an OS vendor, has Microsoft Visual C. IBM, as both an OS vendor and a chip vendor, has XLC (which is the default system compiler for AIX, and the compiler with which both AIX and i/OS are compiled). Intel has their own compiler. Sun/Oracle have their own compiler in Sun Studio.

Then, there are the high-performance compiler vendors like PathScale and The Portland Group, whose compilers (and OpenMP libraries) are used for numbercrunching.

Digital Mars is also still in business. I believe Walter Bright has the unique distinction of being the only person on the planet who managed to create a production-quality C++ compiler (mostly) by himself.

Last but not least we have all the proprietary compilers for embedded microcontrollers. IIRC, there are more microcontrollers sold every year than desktop, mobile, server, workstation, and mainframe CPUs have been sold in the entire history of computing combined. So, those are definitely not niche products.

An honorary mention goes out to TruffleC, a C interpreter(!) running on the JVM(!) written using the Truffle AST interpreter framework that is only 7% slower than GCC and Clang (whichever is fastest on any given particular benchmark) across the Computer Languages Benchmark Game, and faster than both on microbenchmarks. Using TruffleC, the Truffle team was able to get their version of JRuby+Truffle to execute Ruby C extensions faster than the actual C Ruby implementation!

So, these are 6 implementations in addition to the ones you listed which I can name off the top of my head, without even knowing anything about C.

  • 1
    Outside of Microsoft Visual C, most of the C compilers you are mentioning are rarely used. – Basile Starynkevitch Feb 19 '15 at 6:36
  • 6
    MSVC is the big C++ compiler, but for C it's hard to use and permanently stuck in C89; microcontroller compilers are usually target-specific, stuck in C89, and quirky; TruffleC doesn't appear to be available yet (but is interesting, thanks). Pathscale and Digital Mars seem more like the kind of counterexamples I was looking for though. – Leushenko Feb 19 '15 at 8:05
  • 8
    @Mario my meaning isn't that C89 is broken, but C89 is not the up-to-date form of the language; and that does mean fewer compilers that are up-to-date exist. – Leushenko Feb 19 '15 at 8:42
  • 6
    @Leushenko MSVC isn't permanently stuck in C89. There have been some discussions and more C99 features should be added. For starters, most of the C99 library is supported as of MSVC 2015 and a few language features too (mainly the things needed for C++11 though). – Morwenn Feb 19 '15 at 9:28
  • 5
    @Morwenn: Microsoft's policy appears to be that C99 solves no problems that C++ had not already solved, and that if you're doing system programming you should be using the C-like subset of C++ (anything that doesn't require the runtime or where you can't control where the compiler is going to put things - important if you need to ensure that code or data isn't paged out from states where paging is disabled). The only features from C99 will be things required in later C++ specs, and those which are no-brainers to implement. – Mike Dimmick Feb 20 '15 at 10:25
8

How many compilers do you need?

If they have different feature sets, you create a portability problem. If they're commoditised you choose either the "default" (GCC, Clang or VS). If you care about the last 5% performance you have a benchmark-off.

If you're doing programming language work recreationally or for research purposes, it's likely to be in a more modern language. Hence the proliferation of toy compilers for Scheme and ML. Although OCaml seems to be getting some traction for non-toy non-academic uses.

Note this varies a lot by language. Java has essentially the Sun/Oracle toolchain and the GNU one. Python has various compilers none of which are really respected compared to the standard interpreter. Rust and Go have exactly one implementation each. C# has Microsoft and Mono.

  • 1
    It's obvious that there are more interesting reasons to develop an ML compiler... I just thought that the C community being probably three orders of magnitude bigger would balance that effect out. But you might be right, 1000 * 0 is still 0. – Leushenko Feb 19 '15 at 10:46
  • Creating a new compiler is often linked with fragmentation of the community (either caused by or causing). For example, the egcs vs gcc maintainer split. Also, C source compatibility tends to be below 100%. – pjc50 Feb 19 '15 at 11:28
  • @pjc50: The way the standard is written effectively subdivides C into a number of disjoint dialects based upon things like the basic type of int, and will require different compilers to interpret the same source code in very different ways. – supercat Feb 19 '15 at 20:09
  • 5
    I believe, Go has two implementations (the 6g/8g/… toolchain and gccgo). There also used to be a very interesting proprietary commercial implementation called erGo, which was a) a native Windows implementation of Go at a time when neither gccgo nor the original Go compiler worked very well on Windows, b) a company betting on Go, long before it even became 1.0, and c) the first implementation of Go written in Go (gccgo and 6g/8g are both written in C). Both the project and the company vanished, however, before they even got out of closed beta. – Jörg W Mittag Feb 20 '15 at 0:22
6

C/C++ is unique amongst compiled languages in that it has 3 major implementations of a common specification.

Going by the rule of dismissing anything that's not used much, every other compiled language has 0 to 1.

And I think javascript is the only reason you need to specify 'compiled'.

  • 2
    The label "C" is applied to a number of different languages; some define the code uint16_t a=48000u; unsigned uint32_t b=(a*a)/2; as assigning to b the value 8192. Some define it as assigning 1152000000. Most nowadays regard it as Undefined Behavior, and likely to store 3299483648 but make no promise in that regard. – supercat Feb 19 '15 at 20:05
  • 1
    @supercat: Ah, a good weird one with overflows and integer promotion rules. It hinges on using 2 or 2u apparently. – Zan Lynx Feb 19 '15 at 23:46
  • 1
    @ZanLynx: I don't think there are any cases where 2 versus 2u legitimately matters; the only case I know where it might matter involves Undefined Behavior with both 2 and 2u. – supercat Feb 19 '15 at 23:54
  • 3
    @supercat: how would you get undefined behavior from /2u ? Unsigned overflow is defined (as modulo 2^N for implementation-defined N) but division can't even overflow. – MSalters Feb 20 '15 at 12:17
  • 2
    The Undefined Behavior would come from the multiplication of values which would get promoted to signed int, but whose product would not fit in that type. Coercing that result to unsigned int would likely change the interpretation of the resulting value, but would not negate the Undefined Behavior from the preceding calculation. – supercat Feb 20 '15 at 16:34
5

So what is your target language?

SML compilers are often targeting C or something like LLVM (or as seen in your link, the JVM or JavaScript).

If you're compiling C, it's not because you're going to the JVM. You're going to something worse than C. Far worse. And then you get to duplicate that minor hell a bunch of times for all your target platforms.

And sure, C isn't C++, but I'd say that it's closer to C++ than Scheme. It does have its own subset of undefined behavior evilness (I'm looking at you size of built in types). And if you screw up that minutiae (or do it "correctly" but unexpectedly) then you have decades of existing code on vital systems that will tell you how terrible you are. If you screw up an SML compiler, it just won't work - and someone might notice. Someday.

  • SML/NJ and PolyML are both compiling to machine code... – Basile Starynkevitch Feb 19 '15 at 6:31
  • 2
    How is int size " Undefined Behavior" ? And why would be UB be a burden on compiler vendors anyway? The only real burden for compiler writers is that int widths are implementation defined, not unspecified, so you have to document what you did. – MSalters Feb 19 '15 at 16:11
  • @MSalters In reality, compiler writers for an established platform have the burden of matching what others that went before them did. Sometimes this is documented and standardized, sometimes not. It's easy to find what size an int is, but harder to find what is done with register values and where arguments are stored when calling a function (which may change depending on the argument types and return type of the function), struct layout rules, etc. – Random832 Feb 19 '15 at 18:07
  • @MSalters Most people expect int to be 32 or 64 bits but it can be as small as 16 bits. It's not hard at all to produce a number outside the range of [−32767, +32767] and int overflow is UB. There's also char/short getting promoted to int or unsigned int depending on whether int can represent every value of the original type, which can further trigger a conversion from int to unsigned int if the operands had different types and got converted differently, plus potentially another conversion when you assign the result to a variable. – Doval Feb 19 '15 at 18:36
  • @MSalters There's enough leeway in the size of the standard types and enough implicit conversions that I'd bet that for just about any non-trivial C program there's a choice of legal integer sizes that will cause it to do the wrong thing or cause undefined behavior. – Doval Feb 19 '15 at 18:37

protected by gnat Feb 20 '15 at 14:31

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?