What is the result of calling return in a non-void function after calling the function that returns int?

When I use the following code:

int mytest(void); int main(void) { mytest(); return; } int mytest(void) { return 3; } 

What is the return value of main ? I understand that this

  • undefined behavior
  • may cause an error

Edit: big comment: I know this behavior is undefined. Logically, what return value will be created?

Edit 2: Example: http://ideone.com/fAxnNn

-3
source share
4 answers

The problem here is that you don't seem to understand what undefined behavior means.

When you invoke undefined behavior, anything can happen. Your program may crash, it may generate unexpected results, or it may appear that it is working correctly. Making a seemingly unrelated change, such as adding an unused variable or an optional printf call, can change the way undefined behavior appears.

It also means that two different compilers can generate different results for the same code, or one compiler with two different optimization settings can generate different results.

I will give you an example. I compiled your original code on CentOS 5.10 with gcc 4.1.2. At first I compiled without any optimization:

 gcc -Wall -Wextra -g -o /tmp/x1 /tmp/x1.c 

I ran the resulting code and then ran echo $? . The latter prints the exit code of the previous process (i.e., the return value of main ). Result:

 [ dbush@db-centos tmp]$ /tmp/x1 [ dbush@db-centos tmp]$ echo $? 3 [ dbush@db-centos tmp]$ 

Now I will compile the same code on a computer running Windows 7 in Visual Studio 2010:

 cl x1.c 

If I run this and then echo %ERRORLEVEL% to print the return code, I get the following:

 C:\Users\dbush\Documents>x1 C:\Users\dbush\Documents>echo %ERRORLEVEL% 0 C:\Users\dbush\Documents> 

As you can see, gcc and MSVC generate different results for the same code. In one case, it returns 3, and in the other case, it returns 0.

Now let's play with optimization. I compiled the same code on the same CentOS machine with the same gcc version, but with optimization enabled:

 gcc -Wall -Wextra -g -o /tmp/x1 /tmp/x1.c -O3 

Then I ran this twice. Then I got the following result:

 [ dbush@db-centos tmp]$ /tmp/x1 [ dbush@db-centos tmp]$ echo $? 68 [ dbush@db-centos tmp]$ /tmp/x1 [ dbush@db-centos tmp]$ echo $? 36 [ dbush@db-centos tmp]$ 

Thus, I not only get different results when working with different optimization settings, but I get different results that run the same program several times . This can happen with undefined behavior.

So, to answer your question “what value will be returned”, the answer depends on whether you called undefined behavior. You cannot reliably predict what will happen.

EDIT:

Additional examples with updated code.

In gcc without optimization:

 [ dbush@db-centos tmp]$ /tmp/x1 mytest2 = 3 [ dbush@db-centos tmp]$ echo $? 12 

In gcc with -O3 optimization:

 [ dbush@db-centos tmp]$ /tmp/x1 mytest2 = -1078711820 [ dbush@db-centos tmp]$ echo $? 22 [ dbush@db-centos tmp]$ /tmp/x1 mytest2 = -1077511916 [ dbush@db-centos tmp]$ echo $? 22 

In MSVC without optimization:

 C:\Users\dbush\Documents>x1 mytest2 = 3 C:\Users\dbush\Documents>echo %ERRORLEVEL% 0 C:\Users\dbush\Documents> 

In MSVC with optimization /Ox :

 C:\Users\dbush\Documents>x1 mytest2 = 1 C:\Users\dbush\Documents>echo %ERRORLEVEL% 0 C:\Users\dbush\Documents> 

So again, no guarantees.

+1
source

This is not the desired behavior, although not explicitly referred to as undefined behavior. This is a "Breach of Limitations."

Citation C11 , chapter 6.8.6.4

[...] The return without expression should appear only in a function whose return type is void .

and, from the chapter §5.1.1.3, “Diagnostics”,

The corresponding implementation must contain at least one diagnostic message (indicated in the one defined by the implementation) if the translation block or the translation block for preliminary processing contains a violation of any syntax rule or restriction, even if the behavior is also explicitly specified as undefined or defined for the implementation. [....]

In this case, the compiler continues to generate executable code, so yes, the execution of this binary code causes undefined behavior .

The bottom line for main() , which should return an int , should not have a return without an expression. Refrain from writing such code.


[Note: According to this discussion, there is a strong idea that this behavior is undefined, but there is no explicit mention in the standard.]

+9
source

The program, as shown, is not legal C. Using return; in a non-void function like this is a violation of the constraint, and your compiler should complain. Usually this will be a mistake, but the compiler is allowed to create the program, but the standard clearly does not impose any requirements on the behavior of such a program. Therefore, its behavior is not defined (technically, this is slightly different from Undefined behavior, since it is not explicitly specified as "undefined" in the standard).

There is no point in asking questions such as: "What happens when I call Undefined Behavior?" because the answer is always "Anything."

Alternatively, you are allowed to skip the return statement (i.e., exit) if your program does not use the return value. If the program uses the return value, then the behavior is Undefined (not just undefined). In particular, terminating the end of main() is legal. Although there is no reason to allow functions without return , but not with an explicit void return , I assume this is due to the logical insolubility of whether the purpose of the function is accessible (this is a case of a stopping problem).

Of particular interest in this case is that the main() function in question. Options available to the compiler (in addition to eliminating the necessary diagnostics) include (but are not limited to):

  • Complete compilation
  • Optimize return; as the last statement in a function and treat it the same way as main() without the return statement
  • Returns an uninitialized value (which may be a signal value for architectures that support them, or it may be a recently used stack value or something else at all)
+1
source

From the comments (and not from the question), I realized that the main goal is to find what main returns by doing return; . I hope I go in the right direction.

The first thing is a small compiler that allows you to write only return; , and some give a warning, and several compilers give an implicit addition return 0; if nothing returns main.

The second thing, return 0 means successful execution of the program, and if returning something else would mean some runtime error (at least your environment thinks so).

Now come to your doubts: that implicitly returns main by writing return; . I checked with the tool you are using ideone.com and C (gcc-5.1).

With return; he gave

 Runtime error time: 0 memory: 2164 signal:-1 

With return 0; he gave

 Success time: 0 memory: 2164 signal:0 

Using return 1; he gave again

 Runtime error time: 0 memory: 2164 signal:-1 

This signal displays the return value from main

If you use a terminal to run your program, can you use echo $? to get the return value.

So now you can observe that return; and return 1; give the same result (the implicit value returned by it can also be garbage). However, we cannot guarantee this, but now you have all the tools you need to find out.

+1
source

Source: https://habr.com/ru/post/1261282/


All Articles