Skip to main content

Computer Programming - Advanced C

Charles is a software engineer and college professor interested in technology, medicine, economics, and nutrition.

Duff's Device invented by Tom Duff in 1983

Duff's Device invented by Tom Duff in 1983

Advanced C

For whatever reason, C is your language of choice. What are some good reasons to choose C?

A layperson will tell you that C is fast. At least in some cases that's an undeserved stereotype. Are all other languages slow by comparison? No advanced programmer believes that, and neither should you.

C has three advantages over other C-Like languages. Here they are.

  • Low overhead. C deserves its reputation for the ability to produce executable programs that are not much larger than they absolutely need to be. This is vital for low-memory devices. On a modern PC, this is not important at all.
  • Portability. If you need to target new or unusual hardware that has a custom instruction set or non-flat memory space, C and ASM are probably the only available choices though there are exceptions. C is not especially good at portability between versions of linux/Mac/Windows.
  • The ability to do dangerous and bizarre things with memory and flow control. This is where C and C++ truly shine.

Consider the function pictured above. It's a modernized version of the original Duff's Device. Take a close look at it if you haven't seen it before. On first reading, most C programmers will think the do-while mingled with case statements must be a mistake. Once that wears off, some will suggest memcpy() as a replacement (but this is not possible).

For a fuller commentary, see this article.

Variants on a Theme

Consider the function pictured below. It's a modified version of the original Pigeon's Device. The equivalent if statements follow immediately after.

For a fuller commentary, read more about Pigeon's Device here.

Pigeon's Device

Pigeon's Device, invented by Mr Pigeon date unknown

Pigeon's Device, invented by Mr Pigeon date unknown

if (1==mode || (0==mode && test( a, b )))
  return fun1( a, b );

if (2==mode || (0==mode && !test( a, b )))
  return fun2( a, b );

return 0;

Either technique should be used very sparingly for any program that will ever be read by people. This guidance applies to almost all expert-level techniques, use them rarely. It's not because they don't work, it's because they're often hard to read and hard to modify.

C is quirky, flawed, and an enormous success.

— Dennis Ritchie, 1993

union IntFloat
  int ix;
  float fx;


Union means that two variables are stored in the same place in memory. It looks just like a struct and in the example provided ix and fx refer to the same data but have very different meanings. By now you must be aware that a float is made up of the same kind of bits as an int, but in a float some of those bits are dedicated to sign and significant digits of the value stored, and some to a signed exponent. If you've ever wanted to take a peek at those values as a raw bit array, unions are one way to go about it. Simply write a float value to fx and print ix with the %x format string.

Members of a union may be any type including pointers, integers, floating point, structs, or other unions. Unions may be used with typedef in the same way as a typedef struct, or the union name may be omitted entirely.


For social purposes, you should be aware that GOTO may be considered harmful. C and C++ both include goto as a keyword, and I have avoided discussing it in the previous three articles because nobody should ever use goto for any reason. End of discussion, and please do not read the next paragraph.

Goto is an expert level technique. I can think of one legitimate use for it, but there are probably others. Suppose you need to finish from the middle of a nested loop, and for whatever reason you can't put the loop into its own function and use return. There's your goto.


The volatile keyword tells C that a variable may change independently from one moment to the next. It might change because it was modified in another thread, or it might be the result from reading a device address. Whatever the reason, C will carefully read and write a volatile variable from memory exactly as you say, without any fancy caching or logical optimizations. If you happen to do something dangerous or bizarre with flow control, volatile will make sure your writes get written.

A pointer to a volatile int is declared like this.

  • volatile int *p;

Reads and writes to volatile variables may still be done out of order, so volatile must not be used to implement locks, but may be used for limited communication between threads.

Standard Libraries

C was not invented to write large programs. C was never intended to handle data structures with millions of elements. C was invented in the early 1970s on hardware that was already out of date and Ritchie figured rightly that if programmers needed anything more sophisticated than a sort and binary search they were best off writing it themselves.

This makes C easy to learn and cross compilers easy to write, but now we have gigabytes of RAM. In order to write large programs, read them later, and move between C projects with ease we need standardized versions of data structures and algorithms that will always be outside the C standard.

If C is your language of choice then by all means embrace the simplicity. If your C project grows large and complicated, choose or write project-standard versions of queues, trees, hash tables, and all the rest. Just don't expect C to make it easy for you because it'll be a nightmare.

Functions With Variable Argument Count

It amazes me that after 10 years of writing C there are still little corners that I haven't explored fully.

— Tom Duff, 1983


This is all I have to say about C programming. For you, it is not the end.

If you've come this far, programming is an important part of your life and you are either well on your way to, or well past the level of world class expert. As an expert you have to decide for yourself when to take advice from others. I have kept mine to a minimum, done my best to present C as it is, and hopefully this allows you to use C to accomplish your objectives in the very best ways possible.

To my expert audience: did I leave something out, or explain something poorly? Let me know in the comments. To the others: I know some of you read along without the proper practice and understanding, and I hope this series has given you some insight into the world of solving puzzles with computers. Maybe you'll come back someday and walk the expert's path for real.

This article is accurate and true to the best of the author’s knowledge. Content is for informational or entertainment purposes only and does not substitute for personal counsel or professional advice in business, financial, legal, or technical matters.