C suggestions?

You can talk about almost anything that you want to on this board.

Moderator: Moderators

Post Reply
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

C suggestions?

Post by Zepper »

Which code is better, and why? Model 1 or 2?

Code: Select all

//Model 1
int my_function(int value)
{
   switch(value) {
     case 1: return value*3;
     case 2: return value*8;
     ...
     default: return -1;
   }
}

//Model 2
int my_function(int value)
{
   int tmp;
   switch(value) {
     case 1: tmp = value*3; break;
     case 2: tmp = value*8; break;
     ...
     default: tmp = -1;
   }
   return tmp;
}
Last edited by Zepper on Thu Feb 23, 2017 4:24 pm, edited 1 time in total.
zzo38
Posts: 1096
Joined: Mon Feb 07, 2011 12:46 pm

Re: C suggestions?

Post by zzo38 »

The second code is wrong they try to switch from uninitialized values.
(Free Hero Mesh - FOSS puzzle game engine)
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: C suggestions?

Post by rainwarrior »

In a modern context, I'd use the second one, because it should make no difference when compiled with optimizations, but when debugging it gives me the option to put a breakpoint on the return or on individual cases.

In a CC65 context, I'd use the first one because it doesn't optimize and debugging is already inconvenient anyway.


(zzo38 was pointing out a typo, you switched on tmp instead of value by accident, I don't think it was an evaluation of the code style.)
adam_smasher
Posts: 271
Joined: Sun Mar 27, 2011 10:49 am
Location: Victoria, BC

Re: C suggestions?

Post by adam_smasher »

I'd probably use the former, because I find it conceptually simpler.
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: C suggestions?

Post by Zepper »

adam_smasher wrote:I'd probably use the former, because I find it conceptually simpler.
You mean... 1?
adam_smasher
Posts: 271
Joined: Sun Mar 27, 2011 10:49 am
Location: Victoria, BC

Re: C suggestions?

Post by adam_smasher »

Yeah, model 1, with the returns right in the switch statement.
User avatar
dustmop
Posts: 136
Joined: Wed Oct 16, 2013 7:55 am

Re: C suggestions?

Post by dustmop »

From a readability standpoint, I would say version 1, because introducing a temporary variable here doesn't make sense to me. But the example is a bit contrived. Are there a lot of cases like this, and do they all multiply by a constant factor? If so it might be better to use an array of constants. If the cases are different, and more complex, then rainwarrior's point about debugability starts to make sense. I believe version 1 is also more efficient for cc65, but any other compiler should treat them the same.
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: C suggestions?

Post by pubby »

It doesn't matter. 8-)
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: C suggestions?

Post by Zepper »

dustmop wrote:From a readability standpoint, I would say version 1, because introducing a temporary variable here doesn't make sense to me. But the example is a bit contrived. Are there a lot of cases like this, and do they all multiply by a constant factor? If so it might be better to use an array of constants. If the cases are different, and more complex, then rainwarrior's point about debugability starts to make sense. I believe version 1 is also more efficient for cc65, but any other compiler should treat them the same.
It's an example. The code in each case statement doesn't matter. 8-) I'm asking about a model of switch / case: statements. One concrete example is reading the NES PPU. Ages ago, someone said that model 2 provides a common exit point. Early C codes were using model 1 though.
tepples
Posts: 22705
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: C suggestions?

Post by tepples »

I prefer early return where possible, as it more closely resembles how a piecewise function is defined. My having learned some Scheme in my junior year of college is part of it.

A single exit point matters more when a non-optimizing C compiler is all you have, not an optimizing C++ compiler that can make best use of those C++ features that have no theoretical overhead (video). I can think of these cases:
  • Embedding one function's body literally inside another in order to work around a particular C compiler's inability to inline.
  • Cleanup code that must free resources at the end of a function in C. (In C++, you'd use a destructor or scope guard.)
See also "Where did the notion of 'one return only' come from?" on Software Engineering Stack Exchange.
User avatar
gauauu
Posts: 779
Joined: Sat Jan 09, 2016 9:21 pm
Location: Central Illinois, USA
Contact:

Re: C suggestions?

Post by gauauu »

Yeah, it all depends on what you mean by "better."

More readable? Easier to debug/verify? Produces faster code? Produces smaller code?
User avatar
dustmop
Posts: 136
Joined: Wed Oct 16, 2013 7:55 am

Re: C suggestions?

Post by dustmop »

Ah, I'm sorry, I misunderstand the core of question. Yeah, I agree with tepples that "single return only" is a pretty outdated concept. Still I'd prefer version 1 for readability's sake.
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: C suggestions?

Post by rainwarrior »

dustmop wrote:"single return only" is a pretty outdated concept
I don't think much of "one size fits all" rules, but I don't think it's an outdated principle at all. I don't think tepples was saying that, either-- one of the most prominent responses in that article was talking about one of Dijkstra's old screeds, but there are other responses in it that show applications where it's a very good idea to do it.

I listed one practical reason to do it in my response. I actually tend to avoid single-line "if" statements for the same reason: if your debugger has breakpoints per-line, you can't break on it otherwise, so I'd rather waste some whitespace pre-emptively than have to stop running and recompile to debug.

It's not terribly useful to look at an example like this and decide that one is better than the other. It really does depend on the specific application, IMO. Ideas like "never use goto" and "single entry single exit" aren't wrong because they're old, they're wrong because they're being held up as absolutes, instead of as guidelines to help with critical evaluation of your code.
User avatar
Zepper
Formerly Fx3
Posts: 3262
Joined: Fri Nov 12, 2004 4:59 pm
Location: Brazil
Contact:

Re: C suggestions?

Post by Zepper »

One question. By using model 1, a default: is required, right?
User avatar
rainwarrior
Posts: 8731
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: C suggestions?

Post by rainwarrior »

Zepper wrote:One question. By using model 1, a default: is required, right?
It's not required by the language. If there are no applicable cases, the switch statement will just jump to the end, and C has a implicit return if you omit it (undefined return value).

Lots of compilers are capable of giving you an error for not having an explicit return, though, and would be capable of detecting a case like that where the default statement was omitted.

It's almost always a good idea to have a default case.
Post Reply