Author Topic: Function return in C  (Read 8108 times)

0 Members and 1 Guest are viewing this topic.

Offline rakeshm55Topic starter

  • Regular Contributor
  • *
  • Posts: 207
Function return in C
« on: August 21, 2017, 03:54:23 am »
Hi,
I have read in some articles that is recommended to have only one return point for a function rather than having return points at multiple locations.
Why is it so?? How does it make the debugging simple??
 

Offline glarsson

  • Frequent Contributor
  • **
  • Posts: 814
  • Country: se
Re: Function return in C
« Reply #1 on: August 21, 2017, 04:07:51 am »
Why is it so??
It is just like a religious belief.
 
The following users thanked this post: nugglix

Offline goethert

  • Contributor
  • Posts: 22
  • Country: us
Re: Function return in C
« Reply #2 on: August 21, 2017, 04:19:02 am »
what do you mean "return point“ exactly?
 

Offline rstofer

  • Super Contributor
  • ***
  • Posts: 9886
  • Country: us
Re: Function return in C
« Reply #3 on: August 21, 2017, 04:20:36 am »
The mantra is "one way in and one way out" - a true black box.  But rules are meant to be broken and we just had a thread about this last week.  One thing about multiple returns, when you are debugging, once you hit a return statement, you don't have to read the rest of the code.  The other mantra "get in and get out as quick as you can".  This is particularly true for interrupt handlers.
 
The following users thanked this post: rakeshm55, nugglix

Online Ian.M

  • Super Contributor
  • ***
  • Posts: 12807
Re: Function return in C
« Reply #4 on: August 21, 2017, 04:35:44 am »
It becomes important when a function uses resources that have to be cleaned up
properly. If you follow the single return() at the end of the function paradigm, its much much easier to keep the cleanup code consistent with the setup code as there will only be one instance of it.
 
The following users thanked this post: rakeshm55

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: Function return in C
« Reply #5 on: August 21, 2017, 04:40:30 am »
Don't write messy code in a first place, you won't have to clean it up afterwards.

I see no point in artificially limiting your use of a language because some freaks said so. If you want to see a parade of BS and pure stupidity, read MISRA-C rules. That's some out of this world experience.

PS: That one return point thing is also a part of MISRA-C rules, so sometimes you absolutely have to do that, but only because of bureaucracy, it solves no practical issues.
« Last Edit: August 21, 2017, 05:06:56 am by ataradov »
Alex
 
The following users thanked this post: rakeshm55, Yansi

Offline glarsson

  • Frequent Contributor
  • **
  • Posts: 814
  • Country: se
Re: Function return in C
« Reply #6 on: August 21, 2017, 05:04:42 am »
If you follow the single return() at the end of the function paradigm, its much much easier to keep the cleanup code consistent with the setup code as there will only be one instance of it.
But then you have to add code and variables to keep track of what you should clean up. Not to speak about all code and variables added to avoid executing the code between the forbidden return point and the permitted return point at the end (can't have any goats you know).
Using only one return point just adds a number of other problems.
 

Offline KL27x

  • Super Contributor
  • ***
  • Posts: 4099
  • Country: us
Re: Function return in C
« Reply #7 on: August 21, 2017, 05:29:02 am »
Quote
Quote
If you follow the single return() at the end of the function paradigm, its much much easier to keep the cleanup code consistent with the setup code as there will only be one instance of it.
But then you have to add code and variables to keep track of what you should clean up. Not to speak about all code and variables added to avoid executing the code between the forbidden return point and the permitted return point at the end (can't have any goats you know).
Using only one return point just adds a number of other problems.
^This is exactly opposite of the case in assembly programming.

My code can and will jump around anywhere and everywhere, but quite often I direct multiple exit points of a subroutine into one return for the exact reason Ian.M stated. If you leave multiple exit points, you have to redundantly do the cleaning at multiple points in the code. And if you ever change your code in a way that requires modification of this exit cleanup, now you have to track down and modify each exit point. This is not only redundant, but you have higher chance of missing one and creating what could have been an avoidable bug.

I think the single exit point is in general a good idea for code portability. In case you are going to reuse this code, it is easier to describe (in notes to even just yourself, for later) and to implement if you follow this guideline.

Exit points are extremely significant things to me, in order to even read my own code. I use specific tabbing/indentation on exit points so I can understand what I'm looking at.

This probably has nothing to do with C funtions; sorry for the distraction.
« Last Edit: August 21, 2017, 05:34:11 am by KL27x »
 

Offline IanB

  • Super Contributor
  • ***
  • Posts: 11790
  • Country: us
Re: Function return in C
« Reply #8 on: August 21, 2017, 05:39:54 am »
I have read in some articles that is recommended to have only one return point for a function rather than having return points at multiple locations.
Why is it so?? How does it make the debugging simple??

Suppose you want to put a breakpoint at the return point of a function. Where are you going to put the breakpoint if there are multiple returns? Suppose you want to trace the execution path through the code, so you log the function on entry and on exit. How will you do that if there are multiple exits?

It's true, this doesn't matter for everyone, and some people will dismiss these reasons. But you asked, and here are some possible answers.
 

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11536
  • Country: my
  • reassessing directives...
Re: Function return in C
« Reply #9 on: August 21, 2017, 06:31:22 am »
Why is it so??
It is just like a religious belief.
with anyone who lack experience, that is the usual conclusion. there are some reasons to it (similar to an advice of not using goto) as people have mentioned here, but practically sometime its difficult to obey, but it can be usefull as general guideline or something that we need to watch out for... we dont want kids to use unwarranted goto and scattering returns where possible... adults may use it because they know when to use it and when is to not...

Don't write messy code in a first place, you won't have to clean it up afterwards.
and sometime this is also difficult to implement for some program logic. try to strictly obey this general guidelines will make a bloated code with conditional and other unecessary checking. for some program logic, a quick exit or jump is the way to go (if its verified safe to do so)... ymmv..
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline glarsson

  • Frequent Contributor
  • **
  • Posts: 814
  • Country: se
Re: Function return in C
« Reply #10 on: August 21, 2017, 06:38:12 am »
with anyone who lack experience, that is the usual conclusion.
Experience? I've been programming for as long as you have been alive. Seen lots of bugs caused by misguided rules, like having only one return point, over the years.
 
The following users thanked this post: nugglix

Online Mechatrommer

  • Super Contributor
  • ***
  • Posts: 11536
  • Country: my
  • reassessing directives...
Re: Function return in C
« Reply #11 on: August 21, 2017, 06:40:06 am »
so you should be aware of the reason already. yes its also true "its like a religious belief", but religious lessons also have reasons behind it. its just sometime we can understand it sometime we cant, for some obvious reason ;)
Nature: Evolution and the Illusion of Randomness (Stephen L. Talbott): Its now indisputable that... organisms “expertise” contextualizes its genome, and its nonsense to say that these powers are under the control of the genome being contextualized - Barbara McClintock
 

Offline AlfBaz

  • Super Contributor
  • ***
  • Posts: 2183
  • Country: au
Re: Function return in C
« Reply #12 on: August 21, 2017, 06:47:59 am »
The mantra is "one way in and one way out" - a true black box.
What about my sieve() function?  ;D
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6459
  • Country: nl
Re: Function return in C
« Reply #13 on: August 21, 2017, 07:54:48 am »
It is definitely not a (religious) belief, it is a programming paradigm:
Quote
Structured programming is a programming paradigm aimed at improving the clarity, quality, and development time of a computer program by making extensive use of subroutines, block structures, for and while loops—in contrast to using simple tests and jumps such as the go to statement, which could lead to "spaghetti code" that was difficult to follow and maintain.
One extension of this paradigm is the early exit*1 discussed here.

Same with MISRA it has its virtues but also overcomplicated rules but they were created for a reason besides hackling the programmer. If you read the code review of the Toyota begin 2000 and the hundreds of software problems they found you would know there could be good reasons for coding guidelines and paradigms to follow on bigger projects. As long as you are programming your own 8 or 32 bits micro for home projects do what you want, are you programming in a team follow the team/company rules or get sacked.

*1 see next link at early exit:
https://en.wikipedia.org/wiki/Structured_programming

BTW already discussed here:
https://www.eevblog.com/forum/chat/opinions-on-coding-style-re-error-handling/msg1281901/#msg1281901
 

Offline ataradov

  • Super Contributor
  • ***
  • Posts: 11228
  • Country: us
    • Personal site
Re: Function return in C
« Reply #14 on: August 21, 2017, 08:10:56 am »
Have they done a follow up review? I see no indication of MISRA making anything better. Good coding style is a must. But a lot of MISRA is junk, like only having simple for loops with counters starting from 0.

A lot of problems  MISRA detects are avoidable by turning on warnings in modern compilers and actually reading them.

Furthermore, some stuff that MISRA suggests is actively harmful and sabotages compiler error detection.

It may have been useful 10-15 years ago, but compilers advanced quite a bit since then.

Alex
 

Offline MarkF

  • Super Contributor
  • ***
  • Posts: 2523
  • Country: us
Re: Function return in C
« Reply #15 on: August 21, 2017, 08:18:20 am »
Back in the day when almost all code was written in assembly, we had a problem where the computer would crash after 4 to 5 hours of running.  It took 2 of us working 16 hours a day for almost a week to find out that a function with multiple exits had one of those exits that left an extra byte on the stack. Since the function didn't exit that way very often, it took hours for the stack to fill up a crash the computer.

For complex systems and large routines, it's BAD practice to have multiple exits.  Frequently it's a sign of poorly designed and laid out logic.  Granted, C doesn't have the issues with stack manipulation but there are lots of other reasons not to have multiple exits. Especially with multiple programmers modifying the code over it's life cycle.
 

Offline AndyC_772

  • Super Contributor
  • ***
  • Posts: 4208
  • Country: gb
  • Professional design engineer
    • Cawte Engineering | Reliable Electronics
Re: Function return in C
« Reply #16 on: August 21, 2017, 08:21:32 am »
Suppose you want to put a breakpoint at the return point of a function. Where are you going to put the breakpoint if there are multiple returns? Suppose you want to trace the execution path through the code, so you log the function on entry and on exit. How will you do that if there are multiple exits?

Normally, if I want to set a breakpoint in a function, it's because either:

a) something is going wrong in the function, and I want to stop it when it's failing, or

b) I don't necessarily know that something is going wrong, but I want to check what it's doing (or has done) when it's following the normal execution path.

I find multiple returns more naturally useful in those cases.

Online tggzzz

  • Super Contributor
  • ***
  • Posts: 19280
  • Country: gb
  • Numbers, not adjectives
    • Having fun doing more, with less
Re: Function return in C
« Reply #17 on: August 21, 2017, 10:57:01 am »
You should do whatever makes your code readable and easily understandable by other people reading your code in the context in which it is invoked.

As for using a run-time debugger on code with or without multiple exits, people should turn on higher optimisation levels and see how the compiler mutates the code; spaghetti doesn't even begin to describe it! Such transformations are irrelevant provided that the compiler is correct and all programmers on the project fully understand the language. With C/C++, those are unwise presumptions.
There are lies, damned lies, statistics - and ADC/DAC specs.
Glider pilot's aphorism: "there is no substitute for span". Retort: "There is a substitute: skill+imagination. But you can buy span".
Having fun doing more, with less
 

Offline bd139

  • Super Contributor
  • ***
  • Posts: 23018
  • Country: gb
Re: Function return in C
« Reply #18 on: August 21, 2017, 11:07:46 am »
Indeed. C has so much undefined behaviour you occasionally get "oh that was surprising". The optimiser, at least GCC's, mangles the shit out of everything. LLVM/clang is slightly less crazy in that respect. Periodically I go "that was clever" and not "oh my fucking eyeballs"

valgrind, test, profile, valgrind, test, profile, valgrind, test, profile. That's the only way.

I wrote a basic C compiler back in about 1997 that farted out x86 assembly and you don't realise what a turd the code generation side of it is until you try that. You can create very nice normalised code but the x86 instruction set (as any) is so large that there are so many opportunities for peephole optimisation that your compiler will suck instantly unless you try and use the CPU's neat tricks. 6502 was nice. No tricks needed! :)
 

Offline alank2

  • Super Contributor
  • ***
  • Posts: 2183
Re: Function return in C
« Reply #19 on: August 21, 2017, 12:39:10 pm »
I often have two returns in a function.  One at the end that returns a success, and one somewhere along the way that returns fail.  Something that can happen in a function is that may need to cleanup things you have done; for example, if you allocated some memory dynamically using new, you might have to delete it.  If you opened a file that shouldn't be open if the function fails, you might have to close it.  Here is an example:

Code: [Select]
int myfunc()
{
  char *buffer;
  FILE *file;

  buffer=new char[16384];
  if (buffer==NULL)
    {
      fail1:
      return 0;
    }

  file=fopen("myfile.txt","rt");
  if (file==NULL)
    {
      fail2:
      delete[] buffer; //must cleanup buffer
      goto fail1;
    }

  if (someotherfailure)
    {
      fclose(file); //must close file
      goto fail2;
    }

  //file is no longer needed
  fclose(file);

  if (someotherfailure2)
    goto fail2; //we have unrolled where we need to go back to not include closing the file because it is already closed

  //everything is done and was successful

  //cleanup buffer
  delete[] buffer;

  return 1; //success
}

An alternate approach is to use a single group of code for cleanup and return, but you have to set variables ahead of time to NULL in case they never get allocated and then test to see if they need to be cleaned up...

Code: [Select]
int myfunc()
{
  char *buffer;
  FILE *file;
  int ret;

  buffer=NULL;
  file=NULL;
  ret=0;

  buffer=new char[16384];
  if (buffer==NULL)
    goto fail;

  file=fopen("myfile.txt","rt");
  if (file==NULL)
    goto fail;

  if (someotherfailure)
    goto fail;

  //file is no longer needed
  fclose(file);
  file=NULL; //we have to set it to NULL so it isn't attempted to be closed a second time below

  if (someotherfailure2)
    goto fail;

  //everything is done and was successful
  ret=1;

  fail:
  //cleanup
  if (buffer!=NULL)
    delete[] buffer;
  if (file!=NULL)
    fclose(file);

  return ret;
}
 

Offline Kjelt

  • Super Contributor
  • ***
  • Posts: 6459
  • Country: nl
Re: Function return in C
« Reply #20 on: August 21, 2017, 12:52:52 pm »
I often have two returns in a function. 
In my book using "goto" is a big no-go , it should never be used.
Reading your code you are jumping back and although it looks smart since you only clean what has to be done it is only readable since the rest of the code is lean.
If between the fails there are 30 lines of code you have a small disaster in readability for any reviewer.
Besides if any of the three failures occur, you only get a single 0 returnvalue, the main cause of the error should be conserved in my book for the calling software to log or handle.

But as said earlies as many programmers as many taste in programming, that is why companies have coding guidelines so everyone has the same mindset.
 

Offline Howardlong

  • Super Contributor
  • ***
  • Posts: 5315
  • Country: gb
Re: Function return in C
« Reply #21 on: August 21, 2017, 01:24:47 pm »
I often have two returns in a function.  One at the end that returns a success, and one somewhere along the way that returns fail.  Something that can happen in a function is that may need to cleanup things you have done; for example, if you allocated some memory dynamically using new, you might have to delete it.  If you opened a file that shouldn't be open if the function fails, you might have to close it.  Here is an example:

Code: [Select]
int myfunc()
{
  char *buffer;
  FILE *file;

  buffer=new char[16384];
  if (buffer==NULL)
    {
      fail1:
      return 0;
    }

  file=fopen("myfile.txt","rt");
  if (file==NULL)
    {
      fail2:
      delete[] buffer; //must cleanup buffer
      goto fail1;
    }

  if (someotherfailure)
    {
      fclose(file); //must close file
      goto fail2;
    }

  //file is no longer needed
  fclose(file);

  if (someotherfailure2)
    goto fail2; //we have unrolled where we need to go back to not include closing the file because it is already closed

  //everything is done and was successful

  //cleanup buffer
  delete[] buffer;

  return 1; //success
}


Are you sure? While I'm not generally critical of others' code, I draw the line at that I'm afraid, to say I cringed would be an understatement. Perhaps it wasn't the best example?
 

Offline JanJansen

  • Frequent Contributor
  • **
  • Posts: 380
  • Country: nl
Re: Function return in C
« Reply #22 on: August 21, 2017, 01:39:21 pm »
Dont use goto for sure.
Why would someone say not to use return ?, non-sense.
aliexpress parachute
 

Online screwbreaker

  • Regular Contributor
  • *
  • Posts: 61
  • Country: it
Re: Function return in C
« Reply #23 on: August 21, 2017, 02:55:10 pm »
GOTO sometimes is useful to make the code more clean and readable.
Books generally try to discourage the use of GOTO, due to historical reason. In the BASIC era there are no functions, everything was done by GOTO, so the code are mostly very complicated to read.

What you have to keep in your mind is that you have to try to make your code most clean and readable as possible. If more return point or a GOTO can help you to do that, than, use them!
There are no contraindications to use GOTO.

Same thing for ternary operators, some times they are very useful to make the code short and easy to read, some other times they make things more complicated than a simple IF THEN ELSE.
 

Offline Brumby

  • Supporter
  • ****
  • Posts: 12288
  • Country: au
Re: Function return in C
« Reply #24 on: August 21, 2017, 03:40:46 pm »
I'm afraid I would not approve of the use of the goto in that code example.

While I support the preference to avoid using the goto, I do not exclude it completely.  BUT - I have some very simple guidelines for its use.  The first and foremost is that it is always used to branch to a forward point down the code.  Never backward.  The second is that it is not used in normal program logic - only for exception situations.

I've never had to break these yet but, mind you, I haven't been in a position where I needed to consider doing so.
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf