1. 19

  2. 3

    Awesome list. I think the list missed this one: in C++, if an enum is defined inside a struct, its values are namespaced. Whereas in C, the enum values are in the global namespace (i.e. C’s only namespace).

    struct S {
      enum { E } e;
    struct S s;
    s.e = E;    // OK in C, error in C++
    s.e = S::E; // OK in C++, error in C
    1. 2

      The article mixed a couple of things together:

      • Code that compiles as one out of C or C++ and is an error in the other.
      • Code that compiles as C/C++ but has different semantics.

      The first of these is not very interesting because 90% of C++ is in this category. The second is a lot more interesting. In particular, things like void foo() are very bad because they disable type checking on arguments and force the K&R calling convention in C, whereas in C++ they are equivalent to void foo(void). C23 is fixing this and making it an error in C.

      The typical examples of mismatched semantics depend on the fact that C++ doesn’t require tags for referencing struct definitions and so expressions such as sizeof that take a size or a type will see a different value depending on the language.

      I think that dropping file extensions from C++ standard library headers was one of the biggest mistakes that the original C++ standard made. It would be much better to have three different extensions for C, C++ and C/C++ headers. Hopefully the modules tooling will grow support for importing C headers (e.g. the Linux kernel headers that use a lot of syntax that is invalid C++ but that don’t do anything that you can’t map to a C++ AST).