Resume-wise, I've been writing C code since 1985, and I've been an expert on the C Standards Committee (WG14) since 2004. I've written two prior books on C Programming including "Secure Coding in C and C++" and "The CERT C Coding Standard". I also teach Secure Coding in C for NCC Group https://www.nccgroup.trust/us/our-services/cyber-security/se... and I also taught these topics to Computer Science undergraduates and graduate students at CMU for over a decade. So I think I have a good balance of technical skills and communications skills, but you know, pick up a copy and judge for yourself.
I'll buy an extra copy if you can get 'defer' in there too!
Those two features would really be the bee's knees :)
Now that C allows mixing variable declarations in with statements, it becomes annoying that variable declarations can not have labels. This hits particularly hard with the switch/case, but can also apply with ordinary named labels. The syntax to work around this defect is ugly.
The gcc extension for case ranges is really valuable.
Setting the sign bit via a cast should not cause undefined behavior. (for example, going from uint32_t to int32_t) It should just work in the obvious way. Avoiding the problem requires extremely strange code.
I'd like a way to prevent arrays from being replaced by pointers. Assignment could work. Sometimes I really want to pass an array to a function, and I don't mind if that means a megabyte is copied into the function args on the stack. Sometimes I really want to force the huge copy, and other times I'd rather have the compiler keep it in the caller's frame (but callee can mangle it unless it is const) and just pretend that the callee got more than a pointer. Array dimensions need to survive. The callee's prototype should be able to demand specific dimensions or receive them as variables, and the caller should be able to pass a portion of a larger array
The default function parameters of C++ would be useful. The UNIX API for open() would be best done this way, allowing a prototype without the need for stdarg. There doesn't seem to be any reason why default parameters would have to be at the end; a pair of adjacent commas in the middle is a fine way to indicate that the default is to be used for that missing parameter.
It's time to standardize bitfield layout so that bitfields can be used in portable code for purposes like assemblers and disassemblers. (in other words, not for purposes like access to MMIO registers) Microsoft and GNU compilers are already quite compatible on x86_64, so that would be the basis of standardization.
When a bitfield happens to have the size and alignment of a normal integer type, it should be possible to take the address. The resulting type would be a pointer to the integer type of lowest rank having the correct size.
Anonymous unions and structs would be valuable in all scopes, including at file level. This would allow careful data organization to save space, improve cache locality, prevent undesired cache line aliasing, or allow the intentional aliasing of types. Current technology typically involves abuse of the linker, which is well outside the C language.
Being able to do something like an #include, but with a blob of binary data, would be helpful for initializing big arrays. Current practice is to have build scripts convert binary files to C, to have the linker do it, and to rely on assemblers with the capability. None of that is nice to use.
So that we don't have to invoke m4 or do nasty things with recursive macros, the preprocessor could support loops.
There are a few gcc extensions that make macros far more reasonable, including statement expressions and typeof. Add those.