C: (too) many happy returns…

Here’s another quick C thing…

One of the jobs I had used a pretty complete coding style guide for C. One of the things they insisted on was only one “return” in any function that returns values. For example:

int function(int x)
{
   if SOMETHING
   {
      return 100;
   }
   else SOMETHING ELSE
   {
      return 200;
   }
   else
   {
      return 0;
   }
}

The above function returns values 100, 200 or 0 based on the input (1, 2 or anything else). It has three different places where a value is returned. This saves code, compared to doing it like this:

int function(int x)
{
   int value;

   if SOMETHING
   {
      value = 100;
   }
   else if SOMETHING ELSE
   {
      value = 200;
   }
   else
   {
      value = 0;
   }

   return value;
}

Above, you see we use a variable, and then have three places where it could be set, and then we return that value in one spot at the end of the function. This probably generates larger code and would take longer to run than the top example.

But if you can afford those extra bytes and clock cycles, it is a much better way to do this — at least form a maintenance and debugging standpoint.

I have accepted this, but only today did I run in to a situation where this approach would have saved me some time and frustration. In my case, I was encounter a compiler warning about a function not returning a value where it was defined to return a value. I looked and confirmed the function was indeed returning a value. What was going on?

The problem was that it used multiple returns, and did something like this:

int function(int x)
{
   int value;

   if (!ValueIsValid(x)) return;

   if SOMETHING
   {
      value = 100;
   }
   else if >OMETHING ELSE
   {
      value = 200;
   }
   else
   {
      value = 0;
   }

   return value;
}

Somewhere in the program was a check that just did a “return” and the compiler was seeing that, but my eyes were looking at the lower portion of the program where a value was clearly being returned.

I am guessing the function originally did not return a value, and when a return value was added later, that initial “return;” was not corrected, leaving a compiler warning. This warning may have been in the code for a long time and was simply left alone because someone couldn’t figure it out (my situation) or wasn’t concerned about compiler warnings.

Today, the warning bugged me enough that I did a deep dive through the function, line-by-line, trying to figure out what was going on. And I found it. A simple correction could have been this:

int function(int x)
{
   int value;

   if (!ValueIsValid(x)) return 0; // FIXED: Add missing return value.

   if SOMETHING
   {
      value = 100;
   }
   else if SOMETHING ELSE
   {
      value = 200;
   }
   else
   {
      value = 0;
   }

   return value;
}

That resolved the compiler warning, but still left two spots where a value was returned, so I ended up doing something like this:

int function(int x)
{
   int value;

   if (ValueIsValid(x) == true) // do this if valid
   {
      if SOMETHING
      {
         value = 100;
      }
      else SOMETHING ELSE
      {
         value = 200;
      }
      else
      {
         value = 0;
      }
   }
   else // Not valid
   {
      value = 0;
   }

   return value;
}

Now there is only one place the function returns, and it only processeses things if the initial value appears valid.

I will sleep better at night.

I sleep on a soap box.

11 thoughts on “C: (too) many happy returns…

    1. Allen Huffman Post author

      I agree. This should have been an error. Return; from a function that is supposed to return a value would have returned unexpected garbage in a register or something which shouldn’t be allowed to be built.

      Reply
  1. Lee

    I might also argue that returning an arbitrary int (like 0) to indicate to the caller that the parameter was invalid may be considered by some to be bad practice. It’s been WAY too long since I coded in C/C++, but in C# I might either throw an ArgumentException($”Parameter ${nameof(x)} is invalid”) exception, or I might return a more complex object that had the int value as well as a boolean WasSuccessful and maybe an string ErrorMessage the caller could use (or in a more complex system, maybe a collection of ErrorMessages to indicate multiple problems).

    As always, each scenario is unique, and your scenario may be perfectly fine just returning 0 to indicate some “unknown” problem to the caller.

    Reply
    1. Allen Huffman Post author

      My example was just something I typed up. The real routine passed a structure, making a safe copy rather than passing things around by pointers. Seeing a “return;” versus a “return myStruct;” would no doubt not return a populated structure of valid values.

      Reply
  2. James Jones

    Aaargh! For heaven’s sake, if b has type bool, please don’t write “if (b == true)” or “if (b == false)”. Use “if (b)” and “if (!b)” respectively. You don’t say “If the truth value of the proposition ‘it is raining after work’ is true, then let’s go to the park after work”, do you?

    My position on this may not be held by many–I think bool is the only type for which one should do this. I won’t write “if (!ptr)” unless coding standards for a project demand it, and I while I understand its basis, I don’t like C’s having introduced “truthiness” long before Python or JavaScript.

    Reply
    1. James Jones

      Well, of course not; you’d say “If the truth value of the proposition ‘it is raining after work’ is false…” unless maybe you’re Neil Sedaka.

      Reply

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.