One of my (embedded) targets only has a C89 compiler.
I am working on a (hobby) project which targets multiple devices.
Is there a way of compiling (transpiling?) a C11 code base into C89?
(Otherwise I will have to code like it's 1989, literally.)
No I don't think that it is possible for all of C11. C11 has features that simply not exist in C89 or C99: _Generic, _Atomic, _Thread, _Alignof, well defined sequenced before ordering, unnamed struct and union members ... These don't have counter parts in the older versions and would be really difficult to emulate.
For any of these features you would have to rely on extensions of your target compiler, so probably possible for some of the features for one given compiler. But it would be a nightmare to write such a tools that would have plain C89 as a generic target. You'd better implement a C11 compiler directly.
As Carl Norum comments:
What's your target? Would it be hard to port clang/llvm?
This seems to be the promising approach.
It's not necessary to port your target, a port for C89 is enough.
So clang compiles your code to llvm and then llvm to c89 and then you get it.
Related
I just tried to compile a C program with a GNU compiler version 4.9.2. The source code contained a few for int i=0; ... statements and the compiler gave me an error and indicated that I should use -std=c99 in order to compile for loop initial declarations. Apparently, such declarations were not valid before C99.
On an another machine, I have a more recent GNU compiler (8.1.1) where I can compile the same source code without explicitly specifying -std=c99.
Because GNU obviously made their compiler C99 compliant between 4.9.2 and 8.1.1, this lead me to the question if a recent C standard specified that a compiler has to adhere to C99 (or another standard).
Choosing whether to adhere to the C standard, or a particular version of it, is voluntary. The choice does not come from the C standard. It comes from outside. Anybody who makes a C implementation decides whether to conform to the 2018 C standard (or to conform mostly but not completely), whether to conform to the 2011 C standard, whether to conform to some “K&R” notion of C, or something else. Nothing in the C standard says, well, if you are conforming to this standard, your compiler has to conform to some previous version. The standard cannot actually require you to do anything until you choose to conform to the standard.
The C standard and the people who make it and the standards organizations that endorse and publish it have little power to make anybody do anything. They cannot publish the C standard and say you, René Nyffenegger, must obey the 2018 C standard. They are not law-making bodies. There are contracts between private parties which say some project will be produced in accordance to this standard or that standard, but those are private agreements, not public law.
In the 2018 C standard, paragraph 8 of the Foreword says:
For an explanation of the voluntary nature of standards, the meaning of ISO specific terms and expressions related to conformity assessment, as well as information about ISO’s adherence to the World Trade Organization (WTO) principles in the Technical Barriers to Trade (TBT), see the following URL: www.iso.org/iso/foreword.html.
Nor can the standard organizations prohibit you from writing a C compiler that does or does not conform to any particular version of the standard, nor from writing a compiler that conforms largely but not completely.
If you use the name of the C standard commercially, perhaps by claiming conformance to it, the standards organizations might have some legal rights in that regard. That involves international law and the law of many jurisdictions, which I cannot speak to authoritatively. I have not heard of any problems occurring from somebody claiming to conform to the C standard.
The standards organizations do officially withdraw old versions of the standards when a new version is published. This does not prevent you from writing a C implementation that conforms to an old version, but it would prevent you from claiming you are conforming to the current version when you are not. (For example, if a contract you agreed to required you to conform to the current C standard, that would change when the organization publishes a new version and withdraws the old one.)
Prior to GCC 5.0, the default standard it adhered (most closely) to was the C90 standard — specifying no standard was equivalent to specifying -std=gnu90.
From 5.0 onwards, the default was changed to the C11 standard — so specifying no standard was equivalent to specifying -std=gnu11.
Your two compiler versions show this behaviour.
Note that the C standard only prescribes what a compiler must do to adhere to that standard. It does not mandate the behaviour of a compiler with respect to previous or future versions of the standard; there is only one version of the standard as far as the standard is concerned. What compiler implementations do about other versions is entirely up to the compiler writers.
You can, of course, override the default behaviour of GCC with an explicit version:
-ansi
-std=c90
-std=c99
-std=c11
-std=gnu90
-std=gnu99
-std=gnu11
… and some other variations …
The -ansi option is equivalent to -std=c90. The difference between the -std=cXX and -std=gnuXX is that the c version doesn't set the macros for various extensions, so you might have to explicitly indicate that you want to use POSIX interfaces, for example, with options such as -D_XOPEN_SOURCE=700, whereas with gnu version sets those macros automatically.
The each version of the C Standard classifies implementations into two categories: those which comply with that particular version of the Standard, and those that don't. There aren't any C Language Police who will break the kneecaps of anyone who sells non-conforming implementation. Indeed, there are some situations where a non-conforming implementation would be more useful than any conforming implementation could be (e.g. on some small embedded platforms, the amount of code required to produce a full conforming implementation of "printf" might exceed the total code space available). Further, there is no guarantee that a every conforming implementation will be suitable for any particular purpose (indeed, it would be possible to contrive a C implementation which was unsuitable for any purpose whatsoever except to demonstrate that the C Standard doesn't mandate usefulness).
Most quality C development systems can be invoked in different modes which may conform (or fail to conform) with different versions of the Standard, and may be suitable (or unsuitable) for various purposes. From the point of view of the Standard, every different mode in which a development system can be invoked would be a different implementation. I think it would be useful to have the Standard to sub-categorize implementations based upon their support (or lack thereof) for popular features or guarantees that would make them suitable (or unsuitable) for common purposes (e.g. low-level or systems programming) but as yet the Standard has not done so.
I just read: C Wikipedia entry. As far as I know there are 3 different versions of C that are widely used: C89, C99 and C11. My question concerns the compatibility of source code of different versions.
Suppose I am going to write a program (in C11 since it is the latest version) and import a library written in C89. Are these two versions going to work together properly when compiling all files according to the C11 specification?
Question 1:
Are the newer versions of C i.e. C99, C11 supersets of older C versions? By superset I mean, that old code will compile without errors and the same meaning when compiled according to newer C specifications.
I just read, that the // has different meanings in C89 and C99. Apart from this feature, are C99 and C11 supersets of C89?
If the answer to Question 1 is no, then I got another 2 questions.
How to 'port' old code to the new versions? Is there a document which explains this procedure?
Is it better to use C89 or C99 or C11?
Thanks for your help in advance.
EDIT: changed ISO C to C89.
Are the newer versions of C i.e. C99, C11 supersets of older C versions?
There are many differences, big and subtle both. Most changes were adding of new features and libraries. C99 and C11 are not supersets of C90, although there was a great deal of effort made to ensure backwards-compatibility. C11 is however mostly a superset of C99.
Still older code could break when porting from C90, in case the code was written poorly. Particularly various forms of "implicit int" and implicit function declarations were banned from the language with C99. C11 banned the gets function.
A complete list of changes can be found in the C11 draft page 13 of the pdf, where "the third edition" refers to C11 and "the second edition" refers to C99.
How to 'port' old code to the new versions? Is there a document which explains this procedure?
I'm not aware about any such document. If you have good code, porting is easy. If you have rotten code, porting will be painful. As for the actual porting procedure, it will be easy if you know the basics of C99 and C11, so the best bet is to find a reliable source of learning which addresses C99/C11.
Porting from C99 to C11 should be effortless.
Is it better to use C89 or C99 or C11?
It is best to use C11 as that is the current standard. C99 and C11 both contained various "language bug fixes" and introduced new, useful features.
In most ways, the later versions are supersets of earlier versions. While C89 code which tries to use restrict as an identifier will be broken by C99's addition of a reserved word with the same spelling, and while there are some situations in which code which is contrived to exploit some corner cases with a parser will be treated differently in the two languages, most of those are unlikely to be important.
A more important issue, however, has to do with memory aliasing. C89 include
rules which restrict the types of pointers that can be used to access certain
objects. Since the rules would have made functions like malloc() useless if
they applied, as written, to the objects created thereby, most programmers and
compiler writers alike treated the rules as applying only in limited cases (I doubt C89 would have been widely accepted if people didn't believe the rules applied only narrowly). C99 claimed to "clarify" the rules, but its new rules are much more expansive in effect than contemporaneous interpretations of the old ones, breaking a lot of code that would have had defined behavior under those common interpretations of C89, and even some code which would have been unambiguously defined under C89 has no practical C99 equivalent.
In C89, for example, memcpy could be used to copy the bit pattern associated with an object of any type to an object of any other type with the same size, in any cases where that bit pattern would represent a valid value in the destination type. C99 added language which allows compilers to behave in arbitrary fashion if memcpy is used to copy an object of some type T to storage with no declared type (e.g. storage returned from malloc), and that storage is then read as object of a type that isn't alias-compatible with T--even if the bit pattern of the original object would have a valid meaning in the new type. Further, the rules that apply to memcpy also apply in cases where an object is copied as an array of character type--without clarifying exactly what that means--so it's not clear exactly what code would need to do to achieve behavior matching the C89 memcpy.
On many compilers such issues can be resolved by adding a -fno-strict-aliasing option to the command line. Note that specifying C89 mode may not be sufficient, since compilers writers often use the same memory semantics regardless of which standard they're supposed to be implementing.
The newer versions of C are definitely not strict super-sets of the older versions.
Generally speaking, this sort of problem only arises when upgrading the compiler or switching compiler vendors. You must plan for a lot of minor touches of the code to deal with this event. A lot of the time, the new compiler will catch issues that were left undiagnosed by the old compiler, in addition to minor incompatibilities that may have occurred by enforcing the newer C standard.
If it is possible to determine, the best standard to use is the one that the compiler supports the best.
The C11 wikipedia article has a lengthy description of how it differs from C99.
In general, newer versions of the standard are backward compatible.
If not, you can compile different .c files to different .o files, using different standards, and link them together. That does work.
Generally you should use the newest standard available for new code and, if it's easy, fix code that the new standard does break instead of using the hacky solution above.
EDIT: Unless you're dealing with potentially undefined behavior.
It's 2012. I'm writing some code in C. Should I be still be using C89? Are there still compilers that do not support C99?
I don't mind using /* */ instead of //.
I'm not sure about C89 forbids mixing declarations and code. I'm kind of leaning towards the idea that it's actually more readable to have all the declarations in one place, and if it isn't, the function is too long.
VLAs look useful but I haven't needed them yet.
Should I stick with C89 if I don't have a compelling reason not to? Are there other things I haven't considered?
Unless you know that you cannot use a C99-compatible compiler (the Visual Studio C compiler is the most prominent candidate) there is no good reason for not using the nice things C99 gives you.
However, even if you need to support that compiler you can use some C99 features - just not all of them.
One feature of C99 that is incredibly handy is being able to do for(int i = ...) instead of having to declare your loop variable on top of the function - especially since C actually has a block scope. That's the kind of declaration where having it on top really doesn't improve the readability.
There is a reason (or many) why C89 was superseded by C99. If you know for sure that no C99 compiler is available for your particular piece of work (unlikely unless you are stuck with Visual Studio which never supported C officially anyway), then you need to stay with C89 but otherwise you should certainly put yourself in a position where you can benefit from the last 20+ years of improvement. There is nothing inherently slower about C99.
Perhaps you should even consider looking at the newest C11 standard. There has been some important fixes for dealing with Unicode that any C programmer could benefit from (other changes in the standard are absolutely minimal)...
Good code is a mixture of performance, scalability, readability, and maintainability.
In my opinion, C99 makes code easier to read and maintain. Very, very few compilers don't support C99, so I say go with it. Use the tools you have available, unless you are certain you will need to compile your project with a compiler that requires the earlier standard.
Check out these links to learn more about the advantages to C99:
http://www.kuro5hin.org/?op=displaystory;sid=2001/2/23/194544/139
http://en.wikipedia.org/wiki/C99#Design
Note that C99 also supports library functions such as snprintf, which are very useful, and have better floating point support. Also, I find macros to be extremely helpful, especially when working with math-intensive applications (like cryptographic algorithms)
I disagree with Paul R's "bottom line" comment. There are multiple cases where C89 is advantageous for portability.
Targeting embedded systems, which may or may not have compilers supporting C99:
https://groups.google.com/forum/#!topic/comp.arch.embedded/WNvhw3T_9pI%5B1-25%5D
Targeting the TinyCC compiler, as might be required in a restricted environment where installing a gigantic toolchain is either impractical or not allowed. (TCC is no longer being developed, and Bellard's last statement as to ISOC99 support was that it was "heading towards" full compliance.)
Supporting dynamic compilation via libtcc (see above).
Targeting MSVC, as others have noted.
For source-compatibility with projects that may be required by their company to use the C89 standard. This is especially relevant if you're writing an open source library, and want to maximize its application in some industry.
As cegfault noted, some of the C99 features as listed on Wikipedia can be very useful, but none I would consider indispensable if your priority is portability, or any of the above reasons apply.
It appears Microsoft hasn't budged on C99 compliance. SimonRev from Beijer Electronics commented on a related MSDN thread in November 2016:
In broad strokes, the only parts of the C99 compiler that were
implemented are those parts that they needed to keep the C++ compiler
up to date.
Microsoft has done basically nothing to the C compiler since VC6, and
they haven't made much secret that C++ is their vision of the future
of native code, not C.
In conclusion, if you want portability for embedded or restricted systems, dynamic compilation, MSVC, or compatibility with proprietary source code, I would say C89 is advantageous.
Do any c compilers implement any of the C1X features?
P.S.:Is there a way to emulate some of these features in current c compilers
GCC 4.6 has some experimental support for C1X features:
There is now experimental support for some features from the upcoming C1X revision of the ISO C standard. This support may be selected with -std=c1x, or -std=gnu1x for C1X with GNU extensions. Note that this support is experimental and may change incompatibly in future releases for consistency with changes to the C1X standard draft. The following features are newly supported as described in the N1539 draft of C1X (with changes agreed at the March 2011 WG14 meeting); some other features were already supported with no compiler changes being needed, or have some support but not in full accord with N1539 (as amended).
Static assertions (_Static_assert keyword)
Typedef redefinition
New macros in <float.h>
Anonymous structures and unions
Besides gcc, clang has started to add support for C1x features. In particular, there is support for _Generic and _Static_assert. Some other features may be implemented as well, but I haven't tried them.
Based on perusal of the lists and the gcc testsuite (ls gcc/gcc/testsuite/gcc.dg/c1x*):
I looks like _Noreturn is coming in gcc-4.7.
From the testsuite it looks like unicode strings will be too.
It also looks like CMPLX macros are being worked on too.
Maybe _Generic is coming in gcc-4.8.
You may want to check Pelles C out (Only availble for Windows).
I'm used to old-style C and and have just recently started to explore c99 features. I've just one question: Will my program compile successfully if I use c99 in my program, the c99 flag with gcc and link it with prior c99 libraries?
So, should I stick to old C89 or evolve?
I believe that they are compatible in that respect. That is as long as the stuff that you are compiling against doesn't step on any of the new goodies. For instance, if the old code contains enum bool { false, true }; then you are in trouble. As a similar dinosaur, I am slowly embracing the wonderful new world of C99. After all, it has only been out there lurking for about 10 years now ;)
You should evolve. Thanks for listening :-)
Actually, I'll expand on that.
You're right that C99 has been around for quite a while. You should (in my opinion) be using that standard for anything other than legacy code (where you just fix bugs rather than add new features). It's probably not worth it for legacy code but you should (as with all business decisions) do your own cost/benefit analysis.
I'm already ensuring my new code is compatible with C1x - while I'm not using any of the new features yet, I try to make sure it won't break.
As to what code to look out for, the authors of the standards take backward compatibility very seriously. Their job was not ever to design a new language, it was to codify existing practices.
The phase they're in at the moment allows them some more latitude in updating the language but they still follow the Hippocratic oath in terms of their output: "first of all, do no harm".
Generally, if your code is broken with a new standard, the compiler is forced to tell you. So simply compiling your code base will be an excellent start. However, if you read the C99 rationale document, you'll see the phrase "quiet change" appear - this is what you need to watch out for.
These are behavioral changes in the compiler that you don't need to be informed about and may be the source of much angst and gnashing of teeth if your application starts acting strange. Don't worry about the "quiet change in c89" bits - if they were a problerm, you would have already been bitten by them.
That document, by the way, is an excellent read to understand why the actual standard says what it says.
Some C89 features are not valid C99
Arguably, those features exist only for historical reasons, and should not be used in modern C89 code, but they do exist.
The C99 N1256 standard draft foreword paragraph 5 compares C99 to older revisions, and is a good place to start searching for those incompatibilities, even though it has by far more extensions than restrictions.
Implicit int return and variable types
Mentioned by Lutz in a comment, e.g. the following are valid C89:
static i;
f() { return 1; }
but not C99, in which you have to write:
static int i;
int f() { return 1; }
This also precludes calling functions without prototypes in C99: Are prototypes required for all functions in C89, C90 or C99?
n1256 says:
remove implicit int
Return without expression for non void function
Valid C89, invalid C99:
int f() { return; }
I think in C89 it returns an implementation defined value. n1256 says:
return without expression not permitted in function that returns a value
Integer division with negative operand
C89: rounds to an implementation defined direction
C99: rounds to 0
So if your compiler rounded to -inf, and you relied on that implementation defined behavior, your compiler is now forced to break your code on C99.
https://stackoverflow.com/a/3604984/895245
n1256 says:
reliable integer division
Windows compatibility
One major practical concern is being able to compile in Windows, since Microsoft does not intend to implement C99 fully too soon.
This is for example why libgit2 limits allowed C99 features.
Respectfully: Try it and find out. :-)
Though, keep in mind that even if you need to fix a few minior compiling differences, moving up is probably worth it.
If you don't violate the explicit C99 features,a c90 code will work fine c99 flag with another prior c99 libraries.
But there are some dos based libraries in C89 like ,, that will certainly not work.
C99 is much flexible so feel free to migrate :-)
The calling conventions between C libraries hasn't changed in ages, and in fact, I'm not sure it ever has.
Operating systems at this point rely heavily on the C calling conventions since the C APIs tend to be the glue between the pieces of the OS.
So, basically the answer is "Yes, the binaries will be backwards compatible. No, naturally, code using C99 features can't later be compiled with a non-C99 compiler."
It's intended to be backwards compatible. It formalizes extensions that many vendors have already implemented. It's possible, maybe even probable, that a well written program won't have any issues when compiling with C99.
In my experience, recompiling some modules and not others to save time... wastes a lot of time. Usually there is some easily overlooked detail that needs the new compiler to make it all compatible.
There are a few parts of the C89 Standard which are ambiguously written, and depending upon how one interprets the rule about types of pointers and the objects they're accessing, the Standard may be viewed as describing one of two very different languages--one of which is semantically much more powerful and consequently usable in a wider range of fields, and one of which allows more opportunities for compiler-based optimization. The C99 Standard "clarified" the rule to make clear that it makes no effort to mandate compatibility with the former language, even though it was overwhelmingly favored in many fields; it also treats as undefined some things that were defined in C89 but only because the C89 rules weren't written precisely enough to forbid them (e.g. the use of memcpy for type punning in cases where the destination has heap duration).
C99 may thus be compatible with the language that its authors thought was described by C89, but is not compatible with the language that was processed by most C89 compilers throughout the 1990s.