C programming Traps and Gotchas

A discussion of trouble spots in the C programming language.

Please try to follow the formatting I use in the first few posts so that this can be educational to readers.

1 Like

Using = instead of ==

Example:

wrong:


	if (a = b)
		c = a;

right:


	if (a == b)
		c = a;

Discussion:

In C, “a = b” is an expression whose value is b.

Hence, you can do something like this:


	d = c = a = b;

In return for this small convenience, the compiler cannot detect whether the programmer intended to test


	if (a == b)

or


	if (b)

Some programmers have gotten into the habit of coding


	if (1 == a)

instead of


	if (a == 1)

because the compiler will flag “1 = a” as an error.

Edit: added discussion

Forgetting “break” in a switch

Example:

switch (light)
	{
	case red:
		stop();
	case yellow:
		goVeryVeryFast();
		break;
	case green:
		go();
		break;
	}

Discussion:

The “break” was left out in the case for red. The result is likely to be an accident and potentially a bad one.

In C, a switch is implemented as a computed goto. Each case is a label, nothing more, nothing less.

The ideal is for the break to be implied at the end of each case, with another command like “drop” or “fallthrough” for the rare exception. But the language designers wanted to minimize the number of keywords. It is what it is.

Using a single-line comment in a macro definition

Example:


#define	LIMIT		7	// Days in a week

Discussion:

The C preprocessor is a simple text substitution engine which does not really “know C.”

So if I write


	if (Day == LIMIT)

I am really writing


	if (Day == 7	// Days in a week)

and the compiler rewards me with an error message (missing ‘)’).

The solution is to use the classic commenting style in macro definitions, like this:


#define	LIMIT		7	/* Days in a week */

so that the compiler sees


	if (Day == 7	/* Days in a week */)

If a “fallthrough” is required in your algorithm, then I always add a //fallthrough comment so the next programmer knows it was done on purpose.

3 Likes

Other programmers, upon reading this sort of garbage, will ridicule the writer mercilessly. :-p

Always, always add the case

default:
    error();

IMO, garbage in, garbage out. Given a garbage programming language, people will develop garbage habits while others resort to garbage defensive techniques.

As I said in my class, I can write a book on why C is not my favorite programming language, but it is what it is. The industry has chosen to go that way and I do my best to deal with it.

Not always. There are often cases which are ignored. A switch is sometimes more readable than an if followed by a bunch of else ifs.

Ignored cases should still have a default:, don’t leave it out. Even if default is:

   default:
     /* Other cases are specifically ignored */
}

I guarantee you that lint or any other static analysis tool will scream bloody murder about missing default cases.

Another nit-picky thing, a personal preference here: We’re not writing C++, we’re writing C. Use C-style comments /* */ when writing C. :slight_smile:

I believe this was corrected in C99… : )

No, C99 is when the standards committee went off the rails to pander to the C++ dorks. Bjarne S. should be hung up by his testicles for some of that syntax, and operator overloading.

Can’t go down this slippery slope without a fight, or you’d end up with something as nasty as Python.

2 Likes

Best thread I have read on Talk in a long time. Thanks!

1 Like

If in doubt, always refer back to the C FAQ:

http://c-faq.com/

I prefer the horse’s mouth

1 Like

I agree that this is a pretty cool thread. I wrote many a line of C years ago when I worked at Convex. The OS was a BSD port and we parallelized it. It is definitely not the language of choice at my current employer, which is C#, but there are many millions of lines of C still in use.

Thanks for the void malloc().

1 Like

I think I’ve owned a copy for at least 26 years. It just occurred to me that I don’t know exactly where it is, and the sensation is sort of like realizing I left my cell phone at home. I’m guessing it is in the boxes from when I cleared out my desk at the last job almost 8 years ago. No reason to touch it here, but it is still a rather disconcerting feeling.

1 Like

Always use braces…

if (a == b)
  c = a;
  d = a;
  // Why does d change every time?
  // I thought it was only supposed to change when a == b.

…versus…

if (a == b)
  {
  c = a;
  d = a;
  }
3 Likes

But I happen to think that their example for code formatting to be horse hockey.

In my class, I showed examples of the three most common ways to format code and why I prefer one of them. Above all, follow the convention used when working in existing code and at other times, pick one and stick to it.

Edit: lo and behold, the post just above mine is my preference.