Recursion is very useful as a compact and powerful solution to difficult algorithmic tasks, however, it is generally difficult to understand and should be avoided if there is an alternative.
Design your software according to what you know is required now for your current research but bear in mind potential development routes for the future. Don't make the mistake of writing software now for what you think other people may use in the future, you will rarely be correct and you may just be wasting time which could be better spent on research. Doing this generally results is software which suffers from what is reffered to as the second system effect, the software will be too complex for the required task and other people will rarely invest the effort needed to use it. In addition, if the additional complexity is not tested then you may just be introducing bugs which others will have to fix. The software can always be generalised later once the true nature of the required extensions are better understood and tested. If you write your software carefully and clearly others will be able to modify your software to do what they need it to do. Your main goal when considering programming style should be to support people in doing this.
Introduce object oriented mechanisms only when extending existing software to handle your particular problem. ALWAYS check that previous functionality is correctly supported. Do not rush to include object oriented methods into your software too quickly. This will proliferate the location of bugs and make them more difficult to track down. It will also mean that more software has to be modified in order to put the problem right. Only use these methods when the basic framework of the program has already been computationally tested.
Undue use of object oriented mechanisms should be avoided, particularly use of variable function pointers as this makes software difficult for others to understand (take a look at the graphics wrapper functions for the Tv's if you don't believe this).
Do not use global variables directly as a mechanism for exchanging data around C files. It is much better to define access functions to `set' and `get' the data and then to declare them only in the files which require data access. This provides better encapsulation and ensures easier integration with other software. Even this process should be only used when it is absolutely necessary, as generally is is better practice to pass all data as arguments to functions as this approach permits the possibility of parallel threading.
Avoid multiple levels of de-referenceing within a single statement, when for example; extracting structures or pointer variables from other structures. Instead try to explicity extract each structure or function variable before use. This makes the software much more readable and easier to debug.