C Programming — Why Single Exit Point?

Olayiwola Ayinde
4 min readNov 21, 2022

--

There has been a lot of arguments among programmers on whether a function or method should have a single exit point or multiple exit points.

Let’s first understand the meaning of this terms, A single exit point means that a function should have only one return statement placed at the end of the function, while a multiple exit point means that a function can have many returns within the function.

According to the Motor Industry Software Reliability Association (MISRA) software development guideline,

which stated that a function should have only one ‘return’ statement at the very end in the function body, Multiple ‘return’ statements could obscure the code and make it harder to maintain.

The code below shows example of a multiple exit code

int getLargestNumber (int a, int b) {
if(a > b) return a;
else if(b > a) return b;
else return -1;
}

while the code below shows the single exit code

int getLargestNumber (int a, int b) {
int result = -1;
if(a > b) result = a;
else if(b > a) result = b;

return result;
}

According to the International Electrotechnical Commission (IEC 61508) functional safety standard requirement under good programming style, compulsorily

states that there should be a single ‘return’ at the end of a function.

Basically, the notion of a single exit point comes from languages with explicit resource management and structured programming revolution back in the 1970s.

Over the years, I have met with many modern language programmers (Java and Python) who believes that a single-return style is only applicable to old and low level programming languages like Fortran, Assembly and C, because it was common to allocate resources like memory, locks or file handles at the start of the method, and to deallocate them at the end of it, so in this case, an early return can make the programmer to either forget to do the code cleanup and cause a memory leak or locked file. So it makes good sense to impose just one return at the end of the method.

Even Martin Fowler in his book, “Refactoring: Improving the Design of Existing Code”, stated that

… one exit point is really not a useful rule, clarity is the key principle: If the method is clearer with one exit, use one exit point; otherwise don’t.

Now that we’ve seen different programmer’s opinions on this rules given by different safety associations, let’s conclude on the reasons why single exit point is so important and mandatory in your code, especially in C.

Readability

The point of single exit is to write code that is easy to read and understand, log and debug, knowing that there’s only one return at the end of the function, while multiple exit points could make code extremely hard to follow, it also makes a function vulnerable to bugs.

The larger the function and number of return statements, the greater the prone to errors, although I don’t even recommend programmers to write larger functions for clean code reasons, check out one of my git repository, FDCAN driver library , you will notice that the functions are short, understandable with only one single return at the end. I’ve written an example snippet below

static FDCAN_STATUS __fdcan_setupStandardAndExtendedIds (FDCAN_HandleTypeDef *hfdcan, uint32_t* CANIDs) {
uint16_t addressPointer = 0, FBBank_ExtdIncr = 0, FBBank_StdIncr = 0;
FDCAN_STATUS setupStatus = FDCAN_OK;
while(CANIDs[addressPointer]>0) {
if(CANIDs[addressPointer] <= FDCAN_STANDARDID_MAX_SIZE){
if(__fdcan_setupAsStandardId(hfdcan, CANIDs[addressPointer++], FBBank_StdIncr++) != FDCAN_OK) setupStatus = FDCAN_ERROR;
}
else if(__fdcan_setupAsExtendedId(hfdcan, CANIDs[addressPointer++], FBBank_ExtdIncr++) != FDCAN_OK) setupStatus = FDCAN_ERROR;
}
return setupStatus;
}

Resource Management

In modern high level languages like Java and Python where memory management is taken care of automatically, programmers feels that this single return rule is outdated and pointless to them.

Finally, more than one return style is a bad habit in C code, where resources have to be explicitly deallocated, I will give two code examples to show why multiple returns shouldn’t be recommended.

#include <stdio.h>
#include <stdlib.h>

uint32_t writeAndGetTheLargestNumber (uint32_t a, uint32_t b) {
uint32_t result = 0;
FILE *fp = fopen("file_location","w");

if(fp == NULL) {
printf("Error! Could not open file\n");
exit(-1);
}

if(a > b) {
fprintf(fp, "%d is the largest number\n", a);
return a;
}
else if(b > a) {
fprintf(fp, "%d is the largest number\n", b);
return b;
}

fclose(fp);
return result;
}

int main(void)
{
uint32_t res = writeAndGetTheLargestNumber (3, 6);
return 0;
}

As you can see, there are multiple flops in the code above, you would have suggested that there should be fclose in each of the if conditions right?, and also the fprintf appeared in each of the condition, but as programming rule suggested never to duplicate statements in a function. Multiple returns actually makes the code very complex, so the code above would eventually lead to multiple files being open permanently and hence leading to memory leak.

We can as well rewrite the code, making it more memory efficient with fewer bugs.

#include <stdio.h>
#include <stdlib.h>

uint32_t writeAndGetTheLargestNumber (uint32_t a, uint32_t b) {
uint32_t result = 0;
FILE *fp = fopen("file_location","w");

if(fp == NULL) {
printf("Error! Could not open file\n");
exit(-1);
}

if(a > b) result = a;
else if(b > a) result = b;

fprintf(fp, "%d is the largest number\n", result);

fclose(fp);
return result;
}

int main(void)
{
uint32_t res = writeAndGetTheLargestNumber (3, 6);
return 0;
}

In conclusion, I cannot overemphasize the importance of single exit point over multiple exit points in a function, but most of the experiences I had working with only one return in a function makes code readable with lesser errors, and also beautifully give meaning to our programming style.

--

--

Olayiwola Ayinde
Olayiwola Ayinde

Written by Olayiwola Ayinde

Senior Embedded Software Engineer, Roboticist, IoT, Co-Founder & Former CTO ByteHub Embedded, Inventor of CloudX, Electric Vehicle Architect.

Responses (1)