1. 19
    1. 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).