简体   繁体   中英

Function returns value without return statement

Why does following code has a correct output? int GGT has no return statement, but the code does work anyway? There are no global variables set.

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

int GGT(int, int);

void main() {
    int x1, x2;
    printf("Bitte geben Sie zwei Zahlen ein: \n");
    scanf("%d", &x1);
    scanf("%d", &x2);
    printf("GGT ist: %d\n", GGT(x1, x2));
    system("Pause");
}

int GGT(int x1, int x2) {
    while(x1 != x2) {
        if(x1 > x2) {
            /*return*/ x1 = x1 - x2;
        }
        else {
            /*return*/ x2 = x2 - x1;
        }
    }
}

For x86 at least, the return value of this function should be in eax<\/code> register. Anything that was there will be considered to be the return value by the caller.

This means that it's very possible that it will be used as any of local variables. Because both of them are equal at the end, it's more probable that the correct value will be left in eax<\/code> .

It should not work and certainly do not work on all compilers and target OS, even if it works on yours.

The likely explanation is that a function returning int always return something, and it's usually the content of a register. It probably happens that the register used for return value is in your case the same used to compute the last expression before returning from the function (on x86 targets, certainly eax).

This being said, an optimizing compiler detecting that there is no return is allowed to completely remove the code of this function. Henceforth the effect you see (may) disappear when activating higher optimizations levels.

I tested it with gcc:

gcc without optimization: inputs 10, 20 -> result is 10

gcc -O1 inputs 10, 20 -> result is 1

gcc -O2 inputs 10, 20 -> result is 0

If a function is defined to return a value but does not, and the calling function attempts to use the return value, you invoke undefined behavior<\/a> .

Had you compiled with different optimization settings or a different compiler altogether you could end up with different results.

On x86 the return value is stored in EAX register, which "accidentally" is also used by this compiler to store the result of arithmetic operations (or at least subtraction). You can check this by looking at assembly generated by your compiler. I agree with kriss - you can't assume this will always be the case, so it's better to explicitly specify the return value.

"

Official verbiage:

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.

where "undefined benavior" means:

1 undefined behavior
behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements

2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

3 EXAMPLE An example of undefined behavior is the behavior on integer overflow.

C 2011 Online Draft

Believe it or not, a function typed something other than void is not required to have a return statement. It's not enforced by the language grammar, and there is no constraint that a non- void function must contain a return statement. The only constraints are that, if it is present, a return statement in a void function not return the value of any expression, and that a return statement in a non- void function must return the value of an expression.

Why is that the case?

C initially did not have a void data type, and there was no way to specify a subroutine that was only executed for its side effects and didn't return a value. There was no good way to return "nothing", so the return statement was not required. C also at this time had "implicit int " declarations - you could define a function body without a type, and the compiler would assume it was typed int :

foo( a, b )   // old style parameter declarations
  int a;      // still legal, but no longer really used
  char *b;    // for very good reasons
{
  // do something interesting with a and b
}

foo is implicitly typed to return int , even if no value is explicitly being returned. This is okay as long as the caller doesn't try to use foo 's non-existent return value. So a convention sort of developed where "procedures" (functions executed solely for side effects) were not explicitly typed, and had no return statement.

Because legacy code is forever, the behavior with respect to return statements hasn't been changed in more recent versions of the C standard, even though implicit int declarations were removed in C99.

GCC 在这种情况下粘贴“ret”指令,而 clang 粘贴“ud2”并且应用程序在运行时崩溃。

"

You dont need return statement if you are using pointers. Generally, you can return only one value by Return statement, but if you use Pointers you could return how many you want.

scanf("%d", &x1); there you give to function an Adress of X1, not X1 value. pointers works width adresses. you can read books, to learn how to works pointers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM