Welcome to Atalasoft Community Sign in | Help

C/C++ Dialects

Over the years, I've read and written a great deal of code and one thing I've found is that the platform you've most often targeted influences the dialect of the code that you write.  I've also found that I can spot the dialect in code that I'm reading.

This is an good skill.  Actually, this is really a smaller part of a far more important overarching skill: it is vital to learn how to read Other People's Code.  In order to do this, you need to understand their style and their intent.  Knowing the dialect of the code you're reading is a good indication of what the platform for which it was initially targeted, and that gives you an idea of what assumptions the coder might be making.

I was helping a recent hire with Other People's Code and he had a link error like this:

error LNK2019: unresolved external symbol __ referenced in library foo

He had diligently gone searching for "__" and found nothing.  I browsed header files and quickly found that the coder had defined a macro for one platform named '_' (that's one underscore, not two) that was wrapping every string that could be displayed to a user.  I saw this and decided that the original code was target a flavor of UNIX.

Essentially, s/he was trying to create a means of having readable error messages in code but to have localization handle by a global function that had be defined via a macro named '_'.  This is cute and a very UNIX-y thing to do.  It is also almost assuredly the wrong thing to do, if you're trying to write portable code.  The code assumed that all error messages are "char *" where in fact they could, and should be UNICODE strings to be localizable.  The '_' definition was missing in the config file and there was no check to ensure that it had been defined.  In addition, '_' was chosen to be innocuous, which made it even harder to find.

Then again, this code also contained this gem (actual variable names changed to protect the guilty):

if (*count * ("1134182188"[*kind > 9 ? 4 : *kind]-'0') > 4) { /* more code */ }

Yes, C lets you use a string where you would use an array name.  Yes, it's cute, yes, it's compact, but frankly they could've written this as:

if (TotalDataSize(*count, *kind) > 4) { /* more code */ }


if (*count * DataElementSize(*kind) > 4) { /* more code */ }

both of which are far more readable and makes your intent clear.  Heck, while we're at it, those 4's should be replaced with symbolic constants.

I can't stress how important it is to make your intent clear - most of all because chances are you will have to look at that code again when you're fixing bugs.  If you're the author, maybe you can figure it out pretty quickly, but wouldn't it be better for you to be able to figure it out at a glance?

I worked with a colleague at Adobe who referred to using other people's code as akin to wearing someone else's underwear.  Your own underwear is a whole lot more comfortable and you know which pairs still have a good waistband and which pairs have holes, but honestly, you can't count on the luxury of wearing your own underwear and you have to count on someone having to wear yours too, so please try to limit the skid marks, OK?

Published Monday, September 24, 2007 4:34 PM by Steve Hawley
Filed under:


No Comments
Anonymous comments are disabled