I'm also going to go against the grain here and try to make a (slightly humorous) aesthetic case for C. While some people might call it "ugly" for different reasons, such as the lack of higher-level constructs like classes or its reliance on pointers, I find that it isn't the case for me.
TL;DR: In my opinion, C is simple, good C is readable and there's a certain joy to be found in banging bits.
C is simple
Standard C defines only a few basic types and mechanisms to create functions, pointers and arrays out of them. On top of that, there's a small number of composition constructs to make more complex types out of the primitives (like structs and unions). Notice how I described most of the language in two sentences. This means you don't have to keep too many syntactic rules and forms in your head while coding.
Simple is beautiful.
C isn't arcane
Unlike many higher-level languages, you would be hard-pressed to find a lot of weird, unintelligible symbols in C. In the C world, the main facility for both abstraction and "syntactic compression" is the function - semantically a very simple and self-explanatory construct. Good C style encourages almost poetic, readable beauty. To illustrate, let's try to read the following snippet from the Linux kernel. Even without having grasp of the underlying data structures and implementation details, we can make a lot of sense of the following:
bool kthread_freezable_should_stop(bool *was_frozen) { bool frozen = false; might_sleep(); if (unlikely(freezing(current))) frozen = __refrigerator(true); if (was_frozen) *was_frozen = frozen; return kthread_should_stop(); }
The middle of the function reads "in the unlikely event that current is freezing, ask the refrigerator if freezing actually happened". Dr. Seuss couldn't have written it better.
Readable is beautiful.
C is transparent
Unless a C statement includes a function call, you can generally get a very good idea of its run-time cost and side effects. C gives the programmer control and ultimately trusts him or her to do the right thing. We can get a picture of what happens when this (slightly reformatted for SE) snippet out of the implementation of strlen() in the GNU C library runs, because every operator has well-defined semantics. There is no overloading in C.
for (char_ptr = str; ((unsigned long int) char_ptr & (sizeof (longword) - 1)) != 0; ++char_ptr) if (*char_ptr == '\0') return char_ptr - str;
For the purposes of "optimizability", this property is great. Arguably, some higher-level languages make the concise expression of higher-level algorithms easier (like C++ with classes and overloading), but for the purposes C was designed for - acting as a portable assembler - C is ideal. Sometimes, upon successful execution of low-level code, a programmer might feel one with the machine, in a sense (or zero - it's an implementation detail). This isn't to say other languages are bad, not "zen" enough or something silly like that, just that IMO C can be interesting in ways that many other languages have chosen not to be, for many valid reasons.
In my opinion, the three points presented above make manageable the creation of complex - yet efficient - systems, embodied in my mind by Linux. I find that this world appeals to my aesthetic sensibilities and I'd advise anyone considering C as his or her next target to consider these points. I feel that arguments about operating systems and whatnot are better supported by explicitly stating them because one certainly does not need to understand kernels in order to be a successful programmer, but one might find these fields compelling subjectively.