I am using this built-in atomic methods link
It is mentioned that:
The following built-in functions approximately match the requirements
for the C++11 memory model.
However I have tried compiling these methods with std=C99 and std=C89. The program compiles and I get the right results. Is there something I am missing here ?
Does C99 and C89 have a memory model as well ?
It is a compiler extension and therefore it is allowed to provide functionality outside of the what the standard allows but that page does not make it obvious that is the can be used in C.
Fortunately, gcc does have good online documents and if we check out for example the 4.9 series document on C extensions the __atomic Builtins points to the same page.
So that would indicate that it is valid to use in C and it will stick the requirements as laid out in the documentation and so it will work in the C99 as it does in C++. Usually if there is a difference between how a feature/extension is implemented between C and C++ the documents will note this, for example compound literals have significant differences.
Related
I have started using a tool allowing to check the compliancy to MISRA-C 2012. The tool is Helix QAC. During the configuration it requests to select one compiler. My understanding is that MISRA-C (and coding rules in general) are not linked to a compiler toolchain, since one of their objective is portability. Moreover one rule of MISRAC is to not use language extensions (obviously this rule may be disabled or there may be exceptions to it). Helix documentation or support is rather vague about this (still trying to get more info from them) and just mention the need to know the integer type length or the path of standard includes. But the rules analysis should be independant from int size and the interface of standard includes is standard so the actual files should not be needed.
What are the dependencies between a MISRA-C rules checker and the compiler ?
Some of the Guidelines depend on knowing what the implementation is doing - this is particularly the case with the implementation defined aspects, including (but not limited to integer sizes, maximum/minimum values, method of implementing boolean etc)
MISRA C even has a section 4.2 Understanding the compiler which coupled with 4.3 Understanding the static analysis tool addresses these issues.
There is one thing every MISRA-C checker needs to know and that's what type you use as bool. This is necessary since MISRA-C:2012 still supports C90 which didn't have standard support for a boolean type. (C99 applications should use _Bool/bool, period.) It also needs to know which constants that false and true correspond to, in case stdbool.h with false and true is unavailable. This could be the reason why it asks which compiler that is used. Check Appendix D - Essential types for details.
Type sizes of int etc isn't relevant for the MISRA checker to know. Though it might be nice with some awareness of non-standard extensions. We aren't allowed to use non-standard extensions or implementation-defined behavior without documenting them. The usual suspects being inline assembler, interrupts, memory allocation at specific places and so on. But once we have documented them in our deviation to Dir 1.1/Rule 1.1, we might want to disable warnings about using those specific, allowed deviations. If the MISRA checker is completely unaware of a certain feature, then how can you disable the warning caused by it?
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.
I've heard of a lot of cool GCC extensions and built-in functions over the years, but I always wind up forgetting about them before thinking of using them.
What are some cool GCC extensions and built-ins, and some real-life examples of how to put them to use?
GCC provides many features as compiler extensions, off the top of mind and frequently used by me are:
Statement Expressions
Designated Initializers
There are many more documented on the GCC website here.
Caveat:
However, using any form of compiler extensions renders your code non-portable across other compilers so do use them at that risk.
If you want real-life examples of how useful gcc extensions can be then GCC hacks in the Linux kernel is an interesting choice since if it is being used in the Linux kernel then it is probably a good indication it has some real-world impact. As noted before, using extensions does make your code non-portable but clang does make an effort to support gcc extensions which may mitigate some of the impact.
One extensions that is not covered but is used a lot in the Linux kernel is statement expressions, also see Are compund statements (blocks) surrounded by parens expressions in ANSI C?.
The article covers the following features:
Type discovery using typeof
Range extension which includes both Case Ranges and Designated Initializers
Zero-length arrays are flexible array members but with some additions
Determining call address using __builtin_return_addres
Constant detection using __builtin_constant_p
Function Attributes
Branch prediction hints using __builtin_expect
Pre-fetching using __builtin_prefetch
Variable attributes
I recently stumbled over quite a lot of them that are really helpful to emulate the new C11 standard. Actually many of the new features are already there, but with different syntax.
alignment attributes
thread local variables
noreturn attribute to functions
atomic operations (through their __sync_... builtins)
type generic programming
I've written some of that and how to use that with the C11 interfaces in my blog.
Two features that are not covered in functionality by C11 that are really nice, and that I'd very much like to see in future versions of the standard
statement expressions (already mentioned by Als)
__typeof__
I'm continuing to learn C and would like to adhere to whatever is the current standard, but finding a good reference to that seems to be problem.
From what I've found online (mostly through Google and Wikipedia) is that the current standard used today is C99, more formally the ISO/IEC 9899:1999 standard.
When I'm writing C code, I often bring up a browser and do simple web searches for things like finding out the exact return values to the stdio.h function scanf. Mostly I just want to get into a good practice of adhering to the current standard, but even if I search for the specific string "C99 printf" or something like it, there doesn't seem to be one single place to find a definitive spec.
So I have two questions:
1) Is there a central C99 spec that is available online, maintained by the organization responsible for this standard?
[edit]: This first question has already been answered here: Where do I find the current C or C++ standard documents?. Thanks to James McNellis for pointing this out.
2) Is there a program that can parse a C source file to make sure it adheres to the C99 spec? I know there are programs like this to parse XHTML files and it seems like there should be one for C99 as well...
[edit]:
I should also mention that I'm doing C development using gcc, specifically version 3.4.4.
When I go to the main gcc website (http://gcc.gnu.org/) I'm still running into difficulty figuring out which compiler version supports which C specification.
The current standard for Programming
Language C is ISO/IEC 9899:1999,
published 1999-12-01
and
Published ISO and IEC standards can be
purchased from a member body of ISO or
IEC.
From your bestest buds in the standards world, ISO.
It's also worth noting the draft of the NEXT C standard is available in PDF.
Depending on what compiler you use you can ask it to check for you. For example with gcc you would run it like this:
gcc -Wall -Wextra -pedantic -std=c99 -o program program.c
You would replace program.c and program with the name of your program of course.
-Wall and -Wextra provide more warnings and tell you if you have done something funky. -pedantic provides more of that as well.
you can use -ansi if you really want to follow the ansi spec personally I don't use it since I'm lazy but it is more proper.
It is not actually possible to analyse a source file and conclusively determine that it complies with the C99 standard. C is different to XHTML in this regard, because C is a Turing-complete language and XHTML is not.
It is certainly possible to find many instances of non-conformance, but it's impossible to find them all. Consider, for example, a program that generates a printf format string on-the-fly - how can you statically determine that the format string will be conforming? What if it depends on the input given to the program? Consider also a program that right shifts signed integers - if the signed integer in question is never negative, then the program may be conforming, but if not then it is probably relying on implementation-defined results.
The draft for can be obtained here for free. You can also purchase the official one from the ansi store.
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.