I think that is fair. A simple language with a simple memory model is nice to work with.
I also think that it wouldn't be bad for code to be more generic. It is somewhat unnecessary for a procedure to allow an argument of type A but not of type B if the types A and B share all the commonalities necessitated by the procedure. Of course procedures with equivalent source code generate different machine code for different types A or B, but not in a way that matters much.
I believe it is beneficial for the language to see code as the description of a procedure, and to permit this description to be reused as much as possible, for the widest variety of types possible. The lack of this ability I think might be the biggest criticism I have for C from a modern standpoint.
I feel that if C had tagged unions and a little sugar you could write non magical generic functions in C. Non magical meaning unlike C++ etc instead of the compiler selecting the correct function based on the arguments the function itself can tell and handle each case.
Basically you can write a function that takes a tagged union and the compiler will passed the correct union based on named arguments.
int ret = foo(.slice = name);
int ret = foo(.src = str, .sz = strlen(str));
I also think that it wouldn't be bad for code to be more generic. It is somewhat unnecessary for a procedure to allow an argument of type A but not of type B if the types A and B share all the commonalities necessitated by the procedure. Of course procedures with equivalent source code generate different machine code for different types A or B, but not in a way that matters much.
I believe it is beneficial for the language to see code as the description of a procedure, and to permit this description to be reused as much as possible, for the widest variety of types possible. The lack of this ability I think might be the biggest criticism I have for C from a modern standpoint.