12

Occasionally I see major, relatively new, open source C projects targeting very old C standards, typically C89. An example is systemd. These projects have intelligent people at the helm so they probably have a good rationale behind this decision that I don't know about. That benefit of the doubt aside, it almost seems like the rationale is "older and standardized is always more portable and better" which is ridiculous because the logical conclusion would be that FORTRAN is better than C and COBOL is even better than FORTRAN.

When and why is it justified for new C projects to target very old C standards?

I can't imagine a scenario where a user's system absolutely must not update its C compiler but is otherwise free to install new software. The LTS version of Debian, for example, has a gcc 4.6 package which supports C99 and some of C11. I guess that strange scenario must exist though and programs like systemd are targeting those users.

The most reasonable use case I can imagine is where users are anticipated to have exotic architectures on which there is only a C89 compiler available but they are fully willing to install new software. Given the decline in diversity of instruction set architectures, that seems like an excessively hypothetical scenario, but I'm not sure.

  • 10
    "I can't imagine a scenario where a user's system absolutely must not update its C compiler but is otherwise free to install new software." You haven't done enough embedded work ;-) – Philip Kendall Jan 19 '18 at 9:27
  • 1
    @PhilipKendall I haven't done any embedded work. I encourage you to enlighten me with an answer! – Praxeolitic Jan 19 '18 at 9:32
  • 2
    Once a standard is established, it will virtually hold forever. Sometimes longer than 2000 years. – Doc Brown Jan 19 '18 at 13:03
  • 1
    @DocBrown But note that that page explains that the claim that this is a 2000-year-old standard is false. – Jesper Jan 19 '18 at 13:26
  • 1
    When you see something like this, the first question you should ask is, "What platform(s) is it intended to target?", followed by, "What version(s) of C can be compiled on/for said platform(s)?" Then comes, "Which version(s) of C provide the most compatibility with the project's requirements?" And the next would probably be, "What version(s) of C are the majority of the project leads most familiar with?" – Justin Time Apr 8 at 19:05
14

... "older and standardized is always more portable and better" which is ridiculous ...

That statement reached ridiculous when it got to better, which is completely subjective. You don't select a language and standard for a project because half the people at the last meetup you went to were using it; you pick it because you've studied and understood the problem you're solving and determined that it's the right tool for the job.

For standards in general, there's a case to be made on some projects for portability, and that's where selecting an older one has some benefit. This is especially true when you're developing libraries as products, which are a means to someone else's end. The last thing you want to do is write something you can't sell because it requires a compiler that customers you haven't met yet may not have available. Philip Kendall's comment about the embedded world is spot on; there is a lot of that going around, either because people still have to write new code for old, stable platforms or those that don't benefit from the extra features and don't get an up-to-date compiler. When you're in complete control of every aspect of your project, there's no reason not to use the latest standards the environment can support.

For C specifically, there's the question of what you get in exchange for adherence to the latest standard. The K&R-to-C89 transition was a big change that required a lot of effort to clean up old code but ultimately did a lot of good. The changes in C99 and C11 are minor in comparison, and most of the recently-developed C I encounter would still pass C89 because it doesn't use the new features. It's hard to argue that mandating C99 over C89 would be the right thing to do because it supports one-line comments, has a native Boolean data type and can do variable-length arrays. The comments and Booleans have non-ugly workarounds and VLAs can be handled in other, slightly-less-efficient ways. C11 demoted VLAs to optional, and that might be justification for choosing the older C99 if they figure prominently into your implementation.

  • 3
    Well, mixing variable declarations and statements is quite good for comprehensibility. Inline-functions, limited unicode-support and long long are also nice to have. – Deduplicator Jan 19 '18 at 15:41
  • Also, multithreading is sometimes nice to have... – Deduplicator Jan 19 '18 at 15:48
  • @Deduplicator I don't disagree that what's in C99 and C11 are improvements. You can write all the C11 you want if you can make a business case for the value of the nice-to-haves exceeding the value of portability to older environments. File that under "study the problem and find the right tool for the job." – Blrfl Jan 19 '18 at 16:05
  • 2
    Well, the point was that you didn't exactly mention the important improvements. – Deduplicator Jan 19 '18 at 16:34
  • @Deduplicator: I was writing multi-threaded code in the 1990s. Code which relies upon language-based threading features may be unusable on freestanding implementations that can't support everything the Standard requires, while those that use libraries to wrap platform functions that support the functionality they need will be adaptable to any platform that supports such functions. – supercat Oct 12 '18 at 16:57
10

When portability across a wide range of platforms is important. That may include obsolete platforms, and many embedded processors for which only a minimalist compiler is available.

There's also a sense in which C89 is the "lowest common denominator". It was the first properly standardised version, and pretty much any compiler in use today can be assumed to implement some superset of C89.

There's also the issue that Microsoft Visual C++, while it was relatively good at keeping up with C++ standards, stuck at C89 for a long time when in C mode. So anyone not using the latest Visual Studio may be limited to C89.

  • Yes, the argument in favor is portability but the question is if there are actually non-hypothetical systems which can only use a C89 compiler but are compiling new distributions of software. i.e. If I was starting a new C project, how would I decide if adhering to C89 could increase the number of potential users? The MSVC point is good. – Praxeolitic Jan 19 '18 at 14:59
  • 1
    @Praxeolitic It's really a question of whether you're making code that a wide variety of different people will use. Because there will be a lot of people out there using old compilers, either because they cannot upgrade, or because they consider it too much risk and effort to upgrade. – Simon B Jan 19 '18 at 15:36
3

I must admit that I still write pseudo-C89 code (not fully C99-compliant) mainly because of Microsoft. I lean heavily on MSVC for the Windows side and they're still not fully C99-compliant, instead placing the bulk of their focus on C++17 and onwards.

On top of that I'm working on C SDKs against which a lot of plugin developers use MSVC for their plugin development, and some still MSVC 2010. So there are still popular compilers being widely-used on platforms not so exotic (unless you consider Windows exotic) that don't even fully implement C99 yet. When you target wide compatibility with the biggest range of compilers (which is one of the main reasons the SDK is written in C and not C++), there's still a number of them being widely used (at least MSVC) which are behind on the times when it comes to C support. It's almost been a couple of decades since C99 and we still don't have VLAs, e.g., in MSVC AFAIK (haven't checked up on MSVC 2017 yet but given Microsoft's stance on C, I doubt it is much more compliant with C99).

And so there are still unfortunately new compilers that are actually quite good with good optimizers and debuggers that are still not even fully C99-compliant. Of course if it wasn't for this, I'd be jumping all over C11.

Besides source compatibility with plugins and MSVC, there's also interop with other languages. Some other languages use the SDK through an FFI, and some of those FFIs only understand C89. They might not understand bool or _Bool as a simple example when importing functions from a dylib and only understand, say, int.

Yes, the argument in favor is portability but the question is if there are actually non-hypothetical systems which can only use a C89 compiler but are compiling new distributions of software. i.e. If I was starting a new C project, how would I decide if adhering to C89 could increase the number of potential users?

Just noticed this one but kind of echoing Blrfl, the productivity gain by using C99 and C11 isn't so enormous in my case while losing the ability to allow people to write their plugins in MSVC could be a huge cost (especially since the product I work on has the largest market share, by far, on the Windows side and the average user often purchases and downloads many third party plugins). The kind of product I work on is almost halfway between a development environment for programmers/scripters and a user-end product for artists, since so many people want to develop new things on top of it to allow new capabilities and achieve special effects of a kind people haven't seen yet. So in my case it was actually quite a simple decision to favor C89 at least for the SDK.

I suppose you have to kind of look at the compilers around you and try to figure out your target demographic. If you aren't developing a plugin architecture for Windows or doing any embedded programming or trying to build a software development kit that can be used by the widest range of compilers and languages out there, then it certainly makes things easier to reach for C99+ right away. Also maybe consider how much of a productivity boost you get form C99 onwards. I don't benefit that much from things like VLAs since I rely on simple enough ways to use the stack when the data fits and heap otherwise.

But there are a whole lot of things out there lagging behind from popular compilers like MSVC to FFI's in other languages which are cool in the sense that they can import and call C functions directly from a dylib, but might also be a bit behind on the times. So there's a lot more practical business things to consider, depending on your domain, than simply favoring older and standardized for some kind of aesthetic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.