There’s something really simple and elegant in C having all code in functions at a global namespace. You can say “the function you want is X” and there can be no question or confusion about how to call it or where it can be called. “Find the name of function X and read its documentation” is pretty much the only thing you need to do to understand anything. (Aside from all that pesky UB nonsense.)
I’m not sure how this insight is relevant to the subject at hand but I disagree about the “elegant” part. It’s simple and barebones but lacks a lot of expressiveness. Take a C prototype like this for instance:
some_type *my_function(some_other_type *param)
What does this prototype tell you? Well not enough to use the function safely, that’s for sure. Can the parameter be NULL? Does the function take ownership of
param or can I keep using it afterwards? What about the return value, do I own it? Do I need to free it? If so how? Does it borrow or own
param at all? Can the function return NULL in case of an error? Or maybe an ERRNO code masquerading as a pointer somehow?
In Rust all these questions are answered by the function signature without having to find the doc (if it even exists and is accurate) or having to look at the implementation and you don’t even have to pay too much attention because if you use it wrong the compiler will yell at you:
fn my_function<'a>(param: Option<&'a SomeOtherType>) -> Result<SomeType<'a>, ()>
Sure in C you don’t have to bother with the borrow checker, partial borrows or NLL but I don’t think it makes the language more or less “elegant”, it just makes it simpler and less safe.
Also namespacing is a completely orthogonal issue IMO.