Resources for learning C program design

C

C Problem Overview


Coming from a OO background (C#/java) I'm looking for resources to learn how to design pure C programs well.

Whilst i'm familiar with the syntax of C, and i can write small programs, i'm unsure of the approach to take for larger applications, and what techniques to employ. Anything you guys can recommend.

EDIT: I'm happy to completly abandon OO for the purposes of programming in C, my interest is in learning how to structure a program without OO, I want to learn about good ways of designing programs in procedural languages such as C.

C Solutions


Solution 1 - C

This posting has a list of UNIX books which includes most of the classic C/Unix works. For C programming on Windows, Petzold's Programming Windows is probably the best start.

For C program design, some of the UNIX programming books will tell you snippets but I'm not aware of a 'C program architecture' book.

If you're used to java, some tips for C programming are:

  1. Make use of stack. Often when you call a procedure you will want to have variables allocated in the caller's stack frame and pass pointers to them into the procedure you want to call. This will be substantially faster than dynamically allocating memory with malloc() and much less error-prone. Do this wherever appropriate.

  2. C doesn't do garbage collection, so dynamically allocating data items is more fiddly and you have to keep track of them to make sure they get freed. Variables allocated on the stack (see 1) are more 'idiomatic' where they are applicable. Plus, you don't have to free them - this is a bonus for local variables.

  3. Apropos of (2), consider an architecture where your functions return a status or error code and pass data in and out using the stack as per (1).

  4. Get to know what setjmp() and longjmp() do. They can be quite useful for generic error handler mechanisms in lieu of structured exception handling functionality.

  5. C does not support exceptions. See (3).

  6. Lint is your friend. Splint is even friendlier.

  7. Learn what the preprocessor does and what you shouldn't do with it even if you can.

  8. Learn the ins and outs of endian-ness, word alignment, pointer arithmetic and other low-level architectural arcana. Contrary to popular opinion these are not rocket science. If you're feeling keen, try dabbling in assembly language and get a working knowledge of that. It will do much for your understanding of what's going on in your C program.

  9. C has no concept of module scope, so plan your use of includes, prototype declarations, and use of extern and static to make private scopes and import identifiers.

  10. GUI programming in C is tedious on all platforms.

  11. Apropos of (10) learn the C API of at least one scripting language such as Tcl, Lua or Python. In many cases, the best use of C is as a core high-performance engine on an application that is substantially written in something else.

  12. The equivalent of a constructor is an initializing function where you pass in a pointer to the item you want set up. Often you can see this in the form of a call to the function that looks like setup_foo(&my_foo). It's better to separate allocation from initialising, as you can use this function to initialise an item you have allocated on the stack. A similar principle applies to destructors.

  13. Most people find Hungarian notation about as readable as written Hungarian. The exception to this is native Hungarian speakers, who typically find Hungarian notation about as legible as Cuneiform.. Unfortunately, Hungarian notation is widely encountered in Windows software and the entire Win32 API uses it, with the expected effects on the legibility of software written on this platform.

  14. C/Unix books, even really good ones like the ones written by the late W Richard Stevens tend to be available secondhand quite cheaply through Amazon marketplace. In no particular order, get a copy of K&R, Stevens APUE and UNP 1 & 2, the Dragon book, Rochkind, Programming Pearls, Petzold and Richter (if working on Windows) and any of the other classic C/Unix works. Read, scribble on them with a pencil and generally interact with the books.

  15. There are many, many good C/Unix programming resources on the web.

  16. Read and understand the Ten Commandments of C Programming and some of the meta-discussion as to the why's and wherefores behind the commandments. This is showing its age to a certain extent, although most of it is still relevant and obscure compilers are still quite common in the embedded systems world.

  17. Lex and Yacc are your friend if you want to write parsers.

  18. As Navicore points out below (+1), Hanson's 'C Interfaces and Implementations' is a run-down on interface/implementation design for modular architecture with a bunch of examples. I have actually heard of this book and heard good things about it, although I can't claim to have read it. Aside from the C idioms that I've described above, this concept is arguably the core of good procedural design. In fact, other procedural languages such as Modula-2 actually make this concept explicit in their design. This might be the closest thing to a 'C Program Architecture' book in print.

  19. Read the C FAQ.

Solution 2 - C

My concerns going from OO back to C were addressed in David Hanson's "C Interfaces and Implementations".

C Interfaces and Implementations

Seriously, its approach made a huge difference in avoiding accidentally building the large ball of yarn that many non-oo systems wind up as.

Solution 3 - C

Here's some interesting responses from a different question regarding OO programming in C. I made a post about some C code I worked with which basically impelmented object orientation stopping just short by not including virtual methods.

If I were doing C coding, I would use this technique to define 'objects'.

I find keeping Design Patterns in mind is always helpful, and can be implemented in most languages.

Here's a nice PDF discussing object oriented C programming.

Solution 4 - C

minix by tanenbaum

Solution 5 - C

Larger applications? C's strength is when you have to deal with low level things like device drivers, schedulers, and other OS flavored things.

You can make C that operates like OO, but that will utlimately feel like an exercise in re-inventing the wheel..

Solution 6 - C

One minor thing is to order your .c files "backwards" - i.e. put main() at the bottom of the file, and always make sure local functions (ones that aren't in your .h file, that you just wrote for use in that file) live above where they're first used. This means you don't have to write prototypes for them, which is one less thing to fiddle with if you have to change their API.

Then, as a bonus, the 'gD' command in vim will always go to the definition of a function, if it's in the same file :)

Solution 7 - C

While it is written as a somewhat language-agnostic text, Code Complete provides a lot of good guidance on code structure and organization, along with construction practices.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionK MView Question on Stackoverflow
Solution 1 - CConcernedOfTunbridgeWellsView Answer on Stackoverflow
Solution 2 - CnavicoreView Answer on Stackoverflow
Solution 3 - CKieveliView Answer on Stackoverflow
Solution 4 - CPeter MiehleView Answer on Stackoverflow
Solution 5 - CJustJeffView Answer on Stackoverflow
Solution 6 - CC PirateView Answer on Stackoverflow
Solution 7 - CPhil MillerView Answer on Stackoverflow