Designing a better C (I happened to have opened a thread dedicated to this a while ago and it unexpectedly got nowhere) is almost a lost cause. I know it sounds corny, but we now have 50 years to back this up.
Yup. However, what we can kinda-sorta do, is replace the standard C library with something else. (Which is something I've discussed in another thread.)
There are some house-sized warts to deal with, like the
compiler emitting calls to
memcpy() and
memmove()), reserved names, implementation defined details in the standard regarding freestanding C, and they only grow bigger if you want it to be compilable with a C++ compiler also, but they're annoyances, not showstoppers.
What one cannot do, is change the base semantics and rules. The compiler needs to support the ABI you choose. You
can set additional rules, like POSIX C does, if there is a way to tell the C compiler to abide by those rules. You will end up having some compiler dependencies, especially function and variable attributes, but you can choose them from the set already supported by the main C compilers: GCC and clang already have a large common set.
It is also impossible to stop other developers from shooting themselves in the foot. You can only make the robust, sensible ways
easier, but you cannot idiot-proof anything based on top of C.
This is where my view diverges from e.g. DiTBho's. I see things like MISRA C (and Annex K in ISO C11) as futile, and definitely do not want to work under such rules, because I see them as fundamentally flawed in their purpose: that they try to fix a perceived problem at the wrong complexity level.
I can accept the abstractions the (freestanding) C standard does, because to change those would be to fundamentally change the language, and as mentioned by SiliconWizard, none of the alternatives have fared as well as C has for the last half century or so. Thus, while they are far, far from optimal, I see them as
workable; and instead of fighting against them, I try to create interfaces and patterns that take advantage of them.
One of the details I've thought about a lot, and repeatedly see being a crucial piece in many embedded appliances (especially those with limited RAM), is memory allocation. I've discussed arena-based allocators, but fact is, the separate arenas are not the reason why: the reason is, with arena-based allocators you can set practical, reliable run-time limits on any sub-task using a specific arena for allocations.
In a separate thread, peter-f is currently wrestling with a HTTP/HTTPS server running on an STM32 microcontroller. Because the environment does not support arena-based or inheritably-limited allocations, memory use is a critical and hard part of the puzzle to solve. Even with a single heap, if each allocation, reallocation, and free are done with respect to a context, with such contexts themselves forming a tree hierarchy, one can assign reasonable but dynamic limitations for each logical operation/task –– like responding to a HTTP request –– with nothing but standard C. (You can even use a chain of
longjmp()-based handlers, so that if a new allocation in a context cannot be fulfilled, the execution context reverts to the creation of the context failing, with a suitable error. You'll most likely want to add cleanup handlers, closures, too, but it is all quite straightforward to implement. It is the API design, the interface for others to use, that is hard to get right.)
As I hinted and DiTBho confirmed, he actually likes Ada and would apparently like to use it more, his problem being that there is no Ada compiler for some of the platforms he targets. He doesn't need a "better C", he needs Ada.
While I haven't done any serious programming in Ada, I can see its roots, and do believe it – or a strict subset or derivative like SPARK – would be better suited to the tasks MISRA C is usually applied. (However, from outside, it looks like the big companies using Ada tend to hoover all the Ada developers, so that there isn't that big of a free/open source community around it. In particular, what the hell is "GNAT Pro"? Is it just a repeat of what Microchip did to GCC, to be able to hoodwink its customers into paying for a free compiler?)
It is for these reasons, that I firmly, but friendly
, believe that it is wrong to blame the features of C. It just isn't the right tool for the job here.