C is not a high level language, because it does not contain some abstractions that actual high level languages contain.
Here's a non-obvious example. With C, the programmer must always be aware of evaluation order. In fact, this must be specified even in cases where it is not important. For example:
x = a + b;
y = c + d;
Since the values x and y don't depend on each other, they could each be calculated in any order. However, with C, the programmer must explicitly decide on the temporal order that x and y are calculated (the order they appear in a function), even though it doesn't matter. And yes, the C compiler may decide to re-order those calculations under the covers as it decides (for performance reasons perhaps).
With Haskell, when you are outside I/O Monads and such, you don't specify the order of calculations like the above. Those two calculations may appear in that order in the source code, but the Haskell programmer knows that doesn't mean anything. The system may calculate x first, y first, or perhaps neither if those values aren't actually used elsewhere. Temporal ordering is not necessary (or desirable) under most circumstances.
You can never forget about temporal order in C, but there are higher level languages that allow this.