7

I am TA in a course where I have had to give a crash course in C and one of my students asked, why we still use -ansi as part of our compile commands as it is pretty old.

Now, when I was taught C, 10+ years ago, I was told that it was because it is the most widely adopted and used standard of C and that developers really haven't moved on from ANSI/C89. I looked at it before the lecture and all mentions in terms of usage that I could find was 2007 or before. But I also could not find any recommendations to update. I looked through some 50+ opensource C projects on GitHub and all of them also used ANSI in their Make/CMAKE/WAF configuration, so I thought it was still common practices. But is it?

I can see that ANSI (The organisation) official is at C18. So would it be more appropriate to teach the students this or should we stick with C89? I have not been able to find any documentation or description of what is common practice today and I have mostly worked in "legacy" systems that uses 89 or 90.

VLL
  • 9,634
  • 1
  • 29
  • 54
Lars Nielsen
  • 2,005
  • 2
  • 25
  • 48
  • 6
    GCC, Clang and even MSVC have stepped up their game the last few years and now defaults to at least C99 (newer versions of GCC and Clang might even default to C11). Unless your school uses a compiler older than five or so years, then at least C99 should be used. – Some programmer dude Feb 11 '20 at 07:22
  • 1
    Teach them exactly that. Maybe show examples of the difference. Then maybe ask them what they want to use. The rest is opinionated. So, sorry, but I am going to close vote. (Sorry because I actually like the question...) – Yunnosch Feb 11 '20 at 07:23
  • 1
    I believe that C99 is considered the new standard, but C11 is starting to see more widespread usage but there still aren't very many toolchains that implement C18. I've had linker errors trying to compile C18 code because I didn't have an implementation of libc that included the safe io functions in stdio.h, so a good reason is that C18 isn't actually compatible with several platforms. As of right now, only GNU gcc and llvm currently support C18. – Nolan Faught Feb 11 '20 at 07:28
  • 2
    The thing is that C is often used to implemented stuff to be consumed by other languages. Therefore regardless of standard used interface part typically must be restricted to use C89 features, maybe with some few C99 additions that could be properly consumed in other languages (for example `long long int` type but not stuff like flexible arrays or complex built-in). As for implementation, it is often a good idea to use a C++ subset (w dual compilation) for a bit of extra compile-time checks and compatibility for possible future switch to C++. So i'd go with "something else" option. – user7860670 Feb 11 '20 at 07:53
  • 3
    I have recently started a new cross platform project using pure C and found out that even DJGPP (GCC for DOS) supports C99 with gnu extensions (anonymous structs, etc) out of the box ( `--std=gnu99` ). I'm not sure about C11, but C99 with GNU extensions sounds like a safe bet, especially with MSVC supporting that. – Sos Sosowski Feb 11 '20 at 07:55
  • 4
    C90 was still dominant until somewhere 2008:ish. I remember being very sceptical to it myself until I realized how many bug fixes it contained. In retrospect it was mainly old farts hugging C90 out of tradition rather than out of a rationale, because they hated to learn anything new. Yeah there were some mighty strange stuff added, like static & type qualifier in array parameters, digraphs and extensive complex number support. But mostly, the new features were good ones. Particularly the mandatory bug fix to get rid of "implicit int", which remains _dangerous crap_ to this day. – Lundin Feb 11 '20 at 07:59
  • ``, the beginning parts of this book might address your questions. – Eric Feb 11 '20 at 09:45
  • 3
    " I was told that it was because it is the most widely adopted and used standard of C and that developers really haven't moved on from ANSI/C89." - translation: the teacher has not moved on from C89 – M.M Feb 11 '20 at 09:59
  • Consider yourself as a student: "Do I want to learn _the old version of a language_, or _the new version of a language_?" What will be most valuable on the market when I graduate in a few years? If this is a history course, then go with the _old_, else use the _new_. – chux - Reinstate Monica Feb 11 '20 at 12:06

1 Answers1

3

So would it be more appropriate to teach the students this or should we stick with C89?

Unfortunately, this question cannot be answered in an objective way, so it will be a bit opinionated.

If I was a teacher, I would use modern C, that is C11 or newer. But I would also frequently show examples of how it was done in the past. Many of the changes are aimed towards better programming habits.

However, one thing in newer C (which was made non-mandatory in C11) that I would advice against as a teacher is VLA:s. You can read my answer here to understand why: Why VLA:s are bad Note that this is a thing that people disagree on. I'm not claiming I'm correct. VLA:s have their pros, but definitely also their cons. If you want to teach VLA:s, it's important to also teach when and how NOT to use them.

If you want to use an old version, then at least stick to C99. The improvements from C89 to C99 are really major. In most cases, the improvement mainly is about readability convenience, but that should not be underestimated.

Example1, loop variables: (Imho, VERY important for good code structure)

/* C89 */
int i;
for(i=0; i<10; i++) {


// C99
for(int i=0; i<10; i++) {

Not only is this more convenient and readable. It also makes the loop variable disappear when the end of the loop is reached, keeping it local.

Example2, comments:

/* C89 comment */
// C99 comment, and is not valid in C89

Example3, initializers:

struct myStruct {
    uint8_t a;
    char b;
    char *s;
};

struct myStruct createStructC89(uint8_t a, char b, char *s)
{
    struct myStruct x;

    x.a = a;
    x.b = b;
    x.s = s;

    return x;
}

struct myStruct createStructC99(uint8_t a, char b, char *s)
{
    struct myStruct x = {a, b, s};
    return x;
}

The decision might also depend on the goal of the C course.

If it aims towards becoming a C programmer, then I would say that it is important to point out the differences, because most professional C programmers will have to deal with legacy.

On the other hand, consider the cases where C is just chosen as a language for to teach programming for beginners, or if the course aims to come close to the hardware, like courses in computer architecture. Then I would definitely go for C11 or C18. I would consider requiring all handins to compile with gcc -Wall -Wextra -Werror -Werror=vla -pedantic -std=c11

  • -Wall -Wextra Enable extra warnings
  • -Werror Treat warnings as errors. Typical school tasks should have no warnings.
  • -Werror=vla Don't allow vla
  • pedantic Disable many extensions and force the program to (mostly) conform to the standard specified
  • -std=c11 Use C11. Change to C99 or C18 if desired.
klutt
  • 30,332
  • 17
  • 55
  • 95
  • 1
    Loop variable declarations (e.g. `for (int i = 0; ... ;...)` are also helpful in preventing shadowing other counters by allowing the loop variable to be limited to the loop block. Named initializers, in your struct above `struct myStruct x = { .a = 0 };` to zero initialize. Compound literals, etc.. All good benefits. – David C. Rankin Feb 11 '20 at 09:50
  • I think it worth mentioning that C18 is just a C11 with all later fixes applied. At least I don't know of anything major that has been added/changed. So C11 sort of implies C18. –  Feb 11 '20 at 11:23
  • *I would advice against as a teacher is VLA:s* Bad advice. Not using VLAs prevents allocation of true arrays that have dynamic size. – Andrew Henle Feb 11 '20 at 11:24
  • @StaceyGirl I'll consider it. But I don't know if I find that important enough to include in the post. – klutt Feb 11 '20 at 11:27
  • @AndrewHenle Well, that's where very many C coders disagree. Read here why I think they are bad: https://stackoverflow.com/a/58163652/6699433 – klutt Feb 11 '20 at 11:28
  • You mean things like "VLA:s are syntactic sugar for `alloca` and not `malloc`."? Well, [that's not completely correct](https://stackoverflow.com/questions/42094465/correctly-allocating-multi-dimensional-arrays). You can't create a dynamically-sized multidimensional array without VLAs, and that has nothing to do with `alloca()`. – Andrew Henle Feb 11 '20 at 11:33
  • @AndrewHenle Yes, I just edited that answer a little bit. Still, I don't think they are worth it. – klutt Feb 11 '20 at 11:40
  • @StaceyGirl C17/18 7.22.3 specifies returns `NULL` from `malloc(0)` to indicates an error. C11 is not so explicit - possible to interpret `malloc(0) --> NULL` as OK. IMO, `malloc(0)` remains murky. – chux - Reinstate Monica Feb 11 '20 at 12:15