0
/*implementation of strcmp*/

#include<stdio.h>
#include<string.h>

/*length of the string*/
static const int MAX_LENGTH = 4;

/*gets string comparison's return value i.e. the difference between the first unmatched characters*/
int getStrCmpReturn(char[], char[]);
/*gets the maximum of the two integers*/
int max(int, int);

int main()
{
    char string1[MAX_LENGTH];
    char string2[MAX_LENGTH];

    gets(string1);
    gets(string2);

    printf("\n%d", getStrCmpReturn(string1, string2));
    return 0;
}

int getStrCmpReturn(char string1[], char string2[])
{
    //int test = 50;
    int strCmpReturn = 0;
    int i;

    for(i = 0; (i < max((int)strlen(string1), (int)strlen(string2))); i++)
    {
        if(string1[i] != string2[i])
        {
            strCmpReturn = string1[i] - string2[i];
            break;
        }
    }

    return strCmpReturn;    //not required, why?
}

int max(int string1Length, int string2Length)
{
    if(string1Length >= string2Length)
    {
        return string1Length;
    }
    else
    {
        return string2Length;
    }
}

Look at the definition of the function getStrCmpReturn(). It is seen that if the the return statement is removed or commented, the function still returns the value stored in the variable strCmpReturn. Even if an extra variable is added to it, like "int test = 5;" (shown in comments), the function still returns the value stored in the variable strCmpReturn.

How is the compiler able to guess that the value in "strCmpReturn" is to be returned, and not the ones stored in other variables like "test" or "i"?

  • 2
    Different language but otherwise a duplicate: https://stackoverflow.com/questions/9936011/if-a-function-returns-no-value-with-a-valid-return-type-is-it-okay-to-for-the – Yunnosch Aug 20 '18 at 19:27
  • The compiler does not guess: it *warns you* about not returning a value, and if you don't correct the fault it is "anybody's guess" what will happen, not the compiler's guess. – Weather Vane Aug 20 '18 at 19:57

2 Answers2

8

The compiler is not guessing.

You have (without the required return) some undefined behavior. Be scared.

What might happen is that your particular compiler (with your particular compilation flag on your particular machine) has filled (by accident, bad luck or whatever reason) a processor register which contains some apparently suitable return value (as requested by the relevant ABI and calling conventions).

With different compilers (or different versions of them) or a different operating system or computer, or different optimizations flags you could observe some other behavior.

A compiler might use random numbers to allocate registers (or make other decisions); but for the sake of compiler writers, it usually don't ; in other words, compilers writers try to make their compiler somehow deterministic, but the C11 standard (read n1570) does not require that.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 1
    As a matter of fact, both gcc and clang produce results which would be very different from 'expected' behavior - clang will enter endless loop, gcc empties the body of the function out completely. – SergeyA Aug 20 '18 at 19:36
1
6.9.1 Function definitions
...
12 If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined.

C 2011 online draft

In plain English, the behavior of this code is not predictable. It's working as expected for you with your particular combinatoin of hardware, OS, and compiler, but that may not be the case with a different compiler, or even in a different program using the same compiler.

"Undefined behavior" means that the compiler and runtime environment are not required to "do the right thing", whatever the right thing would be. The code may work as expected, or it may crash immediately, or it may corrupt other data leading to a crash later on, or any of a hundred other outcomes.

C's definition is a bit loose in places. There is a constraint (i.e. a semantic rule) that says if a return statement appears in a function that returns anything other than void, then it must be followed by an expression (the return value). Similarly, there's a constraint that says if a return statement appears in a function returning void, then it must not be followed by an expression. However, there are no constraints that say a return statement must be present in either case.

Believe it or not, knowing the history of C, this makes sense. C didn't originally have a void type, and there wasn't a good way to distinguish between functions that computed and returned a value vs. functions that just executed some statements. It was a bit of a pain to force a return on something whose value would never be used anyway, so the presence of return statements are not enforced by either the grammar or any constraints.

Community
  • 1
  • 1
John Bode
  • 119,563
  • 19
  • 122
  • 198