-5

I saw some one write this code

int r, odd_divisors(int a, int b) {
    r = sqrt(b) + 1;
    r -= sqrt(a);
}

AFAIK, the compiler will automatically add return 0; at the end of this code, but in this case, it returns the value of r. Could someone please help me to explain why this happen. Thanks.

UPDATE: This function actually works in this Codefights site: https://codefights.com/challenge/eu4zLJDcv88B2mcCp. You can check for sir_ementaler's solution.

UPDATE 2: Thanks for everyone that pointed out this function is ill format. I knew that. The reason I asked here is because it is the winner's solution in the site I mentioned in the previous update. It looks to me that Codefights must add some other feature to their compiler.

sahara108
  • 2,829
  • 1
  • 22
  • 41
  • 6
    The compiler won't add a `return 0;`. – juanchopanza May 21 '16 at 14:14
  • Which compiler are you using? [It doesn't compile on gcc](https://ideone.com/3tmEio) – Rakete1111 May 21 '16 at 14:14
  • I dont know which compiler. This code is in Codefight site. – sahara108 May 21 '16 at 14:15
  • 4
    This isn't legal C++. A function definition needs a return value type. `odd_divisors(int a, int b) {...}` does not declare a return value type. And if this were a legal function definition, the compiler wouldn't add `return 0;`. The only function with a non-void return value that is not required to have a `return` statement is `main`. – IInspectable May 21 '16 at 14:15
  • Yes I think so. But you can check in this https://codefights.com/challenge/eu4zLJDcv88B2mcCp. Check for sir_ementaler solution. It does compile and return the correct value – sahara108 May 21 '16 at 14:17
  • 3
    `return 0;` will only be added to `main`. – Emil Laine May 21 '16 at 14:18
  • Thanks @tuple_cat. I used to think it will be added for every function. – sahara108 May 21 '16 at 14:19
  • 3
    The code isn't valid C++, period. If it "works", it is because it gets compiled with a non-standards compliant compiler. – juanchopanza May 21 '16 at 14:27
  • Possible duplicate of [Implicit int return value of C function](http://stackoverflow.com/questions/10079089/implicit-int-return-value-of-c-function) – abhishek_naik May 21 '16 at 14:28
  • 1
    One explanation for "it seems to work" is that after `r -= sqrt(a);`, the value of `r` ends up in a register used for the subtraction. This just *might* be the same register used for returning values from a function. In that case, the random value returned just happens to be the same as `r`. – Bo Persson May 21 '16 at 14:40
  • @BoPersson The fun is if you comment the line `r = sqrt(b) + 1;` this function will be wrong and always returns 0. :) – sahara108 May 21 '16 at 15:00
  • You may want to refer to this http://stackoverflow.com/a/9653804 it returns the value of eax register – NcJie Jun 03 '16 at 05:24

2 Answers2

2

The "implicit int" rule that you may know from pre-standard C does not apply to C++. This is invalid code.

Fix your broken code.

Jesper Juhl
  • 30,449
  • 3
  • 47
  • 70
  • Even C89 does not have the implicit int rule, as pointed out [here](http://stackoverflow.com/questions/10079089/implicit-int-return-value-of-c-function/10079180#10079180), it is undefined behavior. – abhishek_naik May 21 '16 at 14:30
  • I know it is undefined behavior. But it actually works in the link I provided. May be that site uses a custom compiler – sahara108 May 21 '16 at 14:33
  • I thought the rule was only removed with C99 - I may have been mistaken. In any case, relying on it is a very bad idea. – Jesper Juhl May 21 '16 at 14:35
  • 2
    There is no undefined behavior here, because it is not legal C++. The compiler is obligated to issue a diagnostic to that effect. – Benjamin Lindley May 21 '16 at 14:35
  • 2
    @sahara108 The thing about undefined behaviour you need to realize is that it is *undefined*. It may do exactly what you expect, but it may also crash or delete all your files. Saying "but it works" in regards to undefined behaviour is meaningless. It may do *anything* - you program is ill formed. – Jesper Juhl May 21 '16 at 14:37
  • Thanks @JesperJuhl. So it must be the Codefights guys uses a custom compiler and add some "unknown" feature. – sahara108 May 21 '16 at 14:49
  • @sahara108 No. That's not the point. The point is that if you do something that is unspecified or undefined then *any* result may occur, but you cannot rely on it. You need to fix your code to have *defined* behaviour or you'll never be able to know what it will do when compiled with any specific compiler or on any specific platform. What you showed is simply wrong code and noone can reason about what it may do. Just fix it already. – Jesper Juhl May 21 '16 at 14:54
  • @JesperJuhl This is not my code. This is the winner's solution. That is the reason why I asked this question. :) – sahara108 May 21 '16 at 14:58
0

The code you posted is not legal C++, but it is very close to legal. The following is legal:

// Example program
#include <iostream>
#include <string>
#include <math.h>

int r, odd_divisors(int a, int b);
int odd_divisors(int a, int b) {
    r = sqrt(b) + 1;
    r -= sqrt(a);
    return 0;
}

int main()
{
    odd_divisors(16,25);
    std::cout << "Hello, " << r;
}

There are two things going on here. Firstly, you can define an int and declare a function in the same statement, but you can't define the function. Allowing this is an obvious compiler extension.

Secondly, failing to return a value from a value-returning function is undefined behaviour. That can mean a crash - but it can also mean doing exactly what you expect. If you don't try to use the value from the function, it is quite likely (but not certain), that nothing very much will happen.

It is of course, much cleaner to make odd_divisors be a void function, or better still, make it return the value and not use a static at all.