> Because C is a very low level language, it imposes very little architectural decisions on higher levels that could cause impedance mismatches.
Remember that it also enforces the idea of types, scopes, blocks, functions, the heap and the data stack quite strictly. It might be a very low level language compared to something like Java, but in terms of being unassuming of architectural intent, I can't say that I agree that it is even in the same ballpark as any of the assembly languages I've used.
Indeed it enforces some function calling convention, which may be an issue if you want to compile a high level language via C, particularly since C does not guarantee tail call optimization.
Also there's no fast way to check arithmetic overflow from portable C, which limits bignum performance.
Due to these limitations better portable assembly languages like C-- have been designed; these days LLVM bitcode is an option as well (which is not actually portable IIRC...).
Remember that it also enforces the idea of types, scopes, blocks, functions, the heap and the data stack quite strictly. It might be a very low level language compared to something like Java, but in terms of being unassuming of architectural intent, I can't say that I agree that it is even in the same ballpark as any of the assembly languages I've used.