There are some major advantages to using the C language for application programming. For one thing, it is relatively efficient. The quality of existing compilers is quite good, and a comfortable programming environment exists for Unix. With ANSI C, the compiler can verify the number and types of function arguments. The use of the keyword static makes it possible to encapsulate information. Interface and implementation can be clearly separated by using header files.
Unfortunately, there are major problems with C as an application language. Perhaps the most serious one is the absence of automatic memory management (garbage collection). The lack of automatic memory management has a tendency to penetrate abstraction barriers and expose implementation details to clients of a module. Furthermore, the lack of automatic memory management in standard C prompts most programmers to try to manage memory in ad hoc ways that create long-term maintenance problems. For example, in a program that requires a great deal of dynamic memory allocation, programmers are tempted to use a great many pointers to objects for the sake of efficiency. However, having a great many pointers to a given object makes it hard (if not impossible) to tell when it's safe to de-allocate that object. To cope with that uncertainty, some programmers resort to copying the object, so that they can be reasonably sure they are the only one using it, so that they can safely de-allocate it when through. This copying may address the problem of too many dangling pointers, but it has the unfortunate effect that objects are no longer being shared. The direct of effect of no longer sharing objects but, rather, relying on copies of them, is that there is far greater possibility of inconsistency between copies of an object---surely a situation we hope to avoid.
Given that ANSI C suffers these limitations as an application language, this guide still offers some helpful principles toward writing better C programs.