In general, the lower level the language, the more rigorous you have to be about style. Many of the same style rules to any language are important. Keep functions short. Keep like methods together. Generalize repeated code. Also, lower level code demands more comments as the code is itself less readable.
In most cases, the methods you'd use to keep things organized are more verbose and more manual. Basically, in C, you get something like encapsulation by keeping related functions in a single source file and using static globals for any data they need to share. You can use this to simulate private data in a class. Or more correctly, this creates something like a "Module", which was the structured programming world's answer to large scale program development before OO came along.
In a similar manner, you can use the same handle method used by system libraries like
fopen to create something like a class. Internally you have a table that maps handles to the "instance data". Or you can also pass a raw pointer back and forth.
In general, try to be as "functional" as you can. Avoid globals and side effects and do as much communication as you can with parameter passing.
One big problem is that you have no help with memory management, so you need to be very rigorous about when you allocate and free memory. Allocated data that goes together should be tied together somehow so that it can all be freed in a single
destroy function. Try to have a general structure to when things are allocated and freed. Also, allocate on the stack whenever you possibly can. One big help is the new dynamic arrays in C99.
The other big problem is the complete lack of collection classes. Best way to solve this is to go looking for third party solutions. You don't want to spend all of your time debugging custom hash table implementations.
You can go all out and fully implement OO by doing by hand what C++ compilers do for you. Make classes by creating structs with function pointers for virtual methods. You can use the same hack C++ does to derive classes by having the "child" class have function pointers to the base class methods in the same order in memory. This is a bad idea for a real program, but can be an interesting learning exercise.