The syntax may be familiar, but I've always thought it's rather arbitrary. There's relatively little over-arching design: it's like they just stuck together features until they had something relatively big. The exact selection of syntactical forms only seems reasonable because it's been around so long and influenced so many popular languages, not because it's particularly neat or simple.
Some syntactic forms are rather annoying. For example, you have different ways to write pointer types: int* foo vs int * foo. (Hmm, I am no good at escaping asterisks in HN comments.) This just causes confusion; conceptually, the * is part of the type, but syntactically it isn't! The array syntax is also rather arbitrary. Why can you do foo[0] or 0[foo] when every other similar operation is an infix operator? Why do you write int foo[] when the type of foo is really an int array (say int[]) rather than an int? Why have both an if-statement and a ternary operator? (Actually, the whole statement/expression divide is annoying especially in how it influenced a whole bunch of other languages.) There are a ton of other little inconsistencies and annoyances (let's not even talk about the C preprocessor). Ultimately, the main thing C syntax has going for it is familiarity, but that seems to be more than enough. I certainly find the syntax strictly worse than a bunch of non-C-like languages, although it's difficult to compare them because they have vastly different semantics.
The semantics are also a problem. As you mentioned, the overabundance of undefined behavior is certainly not good. This certainly causes very real difficulties for even experienced programmers. Then there are a whole bunch of classic C errors that cause rampant security problems and hard-to-debug behavior. Now, some of these are inevitable due to C's providing low-level access for memory management, but others could probably be avoided with different design decisions.
Now, C is obviously a practical and widely-used language. But, as ever, a language's popularity is far more a social issue than a function of its design. The main reasons it seems simple and clear is because it's been around forever, it's influenced the syntax of most popular languages and everyone has either learned C or a very C-like language.
"Why have both an if-statement and a ternary operator?"
Because one is for control of statement execution and one is an expression that returns a value. Two similar-in-purpose but different-in-meaning constructs.
In my experience, if the ?-: operator is written in the same way as the if-else (condition, true, and false parts each on their own line), nested expressions are quite clear and understandable.
Some syntactic forms are rather annoying. For example, you have different ways to write pointer types: int* foo vs int * foo. (Hmm, I am no good at escaping asterisks in HN comments.) This just causes confusion; conceptually, the * is part of the type, but syntactically it isn't! The array syntax is also rather arbitrary. Why can you do foo[0] or 0[foo] when every other similar operation is an infix operator? Why do you write int foo[] when the type of foo is really an int array (say int[]) rather than an int? Why have both an if-statement and a ternary operator? (Actually, the whole statement/expression divide is annoying especially in how it influenced a whole bunch of other languages.) There are a ton of other little inconsistencies and annoyances (let's not even talk about the C preprocessor). Ultimately, the main thing C syntax has going for it is familiarity, but that seems to be more than enough. I certainly find the syntax strictly worse than a bunch of non-C-like languages, although it's difficult to compare them because they have vastly different semantics.
The semantics are also a problem. As you mentioned, the overabundance of undefined behavior is certainly not good. This certainly causes very real difficulties for even experienced programmers. Then there are a whole bunch of classic C errors that cause rampant security problems and hard-to-debug behavior. Now, some of these are inevitable due to C's providing low-level access for memory management, but others could probably be avoided with different design decisions.
Now, C is obviously a practical and widely-used language. But, as ever, a language's popularity is far more a social issue than a function of its design. The main reasons it seems simple and clear is because it's been around forever, it's influenced the syntax of most popular languages and everyone has either learned C or a very C-like language.