Unless you use GCC's cleanup extension (which runs an arbitrary function when leaving a scope, similar to Rust's Drop trait). Or evil macros which turn innocent-looking code into something else (a well-known project, in some compilation modes, redefines the "if" keyword to track how many times each branch is taken). Or both at the same time (like hiding GCC's cleanup extension with a macro).
This is an oversimplification. Writing fast code for modern processors is all about how much time you spend waiting for memory.
e.g. bubblesort will beat quicksort for tiny lists or large lists which are already sorted.
Or, put another way, 1000 operations against 1ns latency memory (L1) has the same performance as 10 operations against 100ns latency memory (RAM).
Since performance is exactly a measure of the number of imperative steps that need to happen in a program, low level imperative langauages are going to win in performance-obviousness every time. (Rust probably beating C in terms of avoiding memory problems, C probably beating rust in terms of not supporting language constructs that can make a single line worse than O(1).)
"Accidentally" asking the language to do something time-expensive is as impossible in C as forgetting a free() in Haskell.