Then C++ has failed fundamentally, because most well-written C programs
of any reasonable complexity do not compile as C++.
The major reason for this, I think, is that casting the result of
malloc() (or calloc() or realloc()) is not required (and strongly not
recommended) in C, but necessary in C++. If it were not for that, I
think that most well-written C *would* be valid C++. (I'm ignoring
things like <stdio.h> vs. <cstdio>, which were added to C++ relatively
late in its development.)
But apparently the fact that casting the result of malloc() in C is a
bad idea wasn't clearly understood in the early days of ANSI C. The
examples in K&R2 do cast the result of malloc(). And the K&R2 errata
list, <
http://cm.bell-labs.com/cm/cs/cbook/2ediffs.html>, says:
142(6.5, toward the end): The remark about casting the return
value of malloc ("the proper method is to declare ... then
explicitly coerce") needs to be rewritten. The example is correct
and works, but the advice is debatable in the context of the
1988-1989 ANSI/ISO standards. It's not necessary (given that
coercion of void * to ALMOSTANYTYPE * is automatic), and possibly
harmful if malloc, or a proxy for it, fails to be declared as
returning void *. The explicit cast can cover up an unintended
error. On the other hand, pre-ANSI, the cast was necessary, and it
is in C++ also.
At the time K&R2 was written, and at the time that Mr. Stroustrup made
his statement that well-written C tends to be valid C++ (I don't have
the exact wording), it was a reasonable statement. As both languages
have evolved, along with our understanding of them, it has become
somewhat less true.
C is, as always, *nearly*, but not quite, a subset of C++. It's still
reasonably straightforward to write code that's valid in both C and
C++ (write good C code, add casts for malloc() and friends, avoid
identifiers that are keywords in C++ but not in C, and a few other
things). But there is rarely a good reason to do so.