Please also consider the other types of allocation:
int foo;
outside of a block will allocate a global variable, which is alive during the whole lifetime of your process, and visible for other modules of the program.
static int foo;
outside of a block is the same but visible in the actual module only.
int foo;
inside a block is alive only while the code in the block runs, then it's destroyed.
static int foo;
inside a block is visible in the block only, but it preserves its value for the entire lifetime of the process.
I'm doing a lot of embedded C coding, and using malloc() is absolutely prohibited. And it's entirely possible. You typically need malloc() if you don't know the size of your problem at compile time. But even in some cases like that, you can replace dynamic memory allocation with other techinques like recursion, line-based processing etc, etc.