Not sure what dead weight comes with as I'm not a C standards pedant, but there's clearly some welcome niceties that don't seem to ruin the language in my experience.
Variable modified types are cool - you can use them to cast a raw pointer to a N times N matrix and the math works out - you can just do m[i][j] instead of m[i*N+j].
But the evil part is when you declare variable length arrays on the stack. There are exactly two possible scenarios - either you have an upper bound on the allocated size or you don't.
If you have an upper bound and it is reasonably small, use a fixed length array on the stack - there is no point in saving a few bytes on the stack.
If you don't have an upper bound, VLAs will blow your stack, given the right inputs.
If you need a way to allocate unbounded arrays in a LIFO pattern, which 99% of the time are tiny, use a dedicated index-incrementing allocator, falling back on malloc when necessary. You can even cast the resulting pointer to a variably modified type, so that sizeof math works out
I'll allow of course that they don't "ruin the language" they just increase the cognitive burden of reading code.
vv = 3f_add(&v, &(3f_t){.x = .1, .y = .2, .z = .3 });
vs. having to declare and name the literal 3f_t beforehand, wasting my time and cluttering up the code with noise.But then, after looking back at my old code, I struggled and crafted my 1SLOC guiding principle. I never looked back.
Wasting time when writing code is actually an investment into future read speed.
I even wrote some time ago about my rationale for 1SLOC https://blog.pwkf.org/2022/09/18/always-optimize-for-dummies...