I was facing the same issue. Here's one solution I found. I'm not saying it solves everything, but it helps greatly: Naming conventions.
* Avoid all names like i, j, tmpvariable, and such.
* camlCase vs using_underscores.
Pick one. It doesn't matter which but stick to it. Also try to make sense of it. I use underscores because I find it easier to do searches and grep. If my function is called "intialize_variable" I can do single grep on "initialize" for example. The important thing is to show consistency and uniformity.
* Function order. If I'm studying 2 functions, I'd much more rather have them in the same location in the same file. Ideally they would fit together on the screen at all time. It beats scrolling back and forth between functions.
* Finally, code "defensively". Which means, take a little extra time when writing the code the first time, to make it easier for you to come back. That means comments, filenames, makefiles, README files, keep as much info as you can. Just like Knuth used to say:
"Instead of focusing on telling the computer what to do, let's focus on telling other people what we want the computer to do".
The problem I'm currently facing is that I'm writing too many short functions instead of one big function block. It makes my code too verbose and all these extra function declaration makes the code impossible to follow.