简体   繁体   中英

Why does this function returns size of array when there is no return statement?

I'm getting output as 8 for this program. Why is this function returning size of array when there is no return statement? It is working properly when I write the return statement but I'm still curious why this function is returning the size of array. I thought it should return garbage value.

#include <stdio.h>
int sumofelements(int A[],int size)
{
    int i,sum=0;
    for(i=0;i<size;i++) 
        sum = sum + A[i];
}

int main()
{
    int A[]={3,4,5,6,3,6,1,10};
    int size=sizeof(A)/sizeof(A[0]);
    int total=sumofelements(A,size);
    printf("sum of the elements=%d",total);
}

The behavior is undefined. Any value is possible, including the observed behavior. And on some exotic architectures, a trap value might cause other strange behavior.

For your particular case, the place where sumofelements is expected by main to have placed its return value (some CPU register) happens to contain the value of size , but no guarantee whatsoever: it might not on a different combination of CPU/OS/compiler/set of options/time of day...

Use gcc -Wall -Werror or a similar warning level to avoid such silly mistakes.

You can look at the assembly and behavior on Godbolt's Compiler Explorer and play with compiler flags and compiler versions to see how volatile the behavior is. With -O2 , both gcc and clang generate a simple ret instruction for sumofelements and do not even call this function for the printf call.

Not explicitly returning a value from a non-void function (except main() ) results in Undefined behavior . This means that anything can happen: a crash, returning garbage value, or worse of all, the expected value!

You should always return something (meaningful) from a non-void function.

Return values are picked from eax which is a register on your CPU (registers are like your CPU's own place to store some small amounts of data outside of RAM) it happened to be that eax contained the size of the array just before your function ended.

Probably in i < size , size is stored in eax and is not modified any further until your function ends, but you would have to objdump -d your program and paste it here for me to say anything certain.

If you want to learn more type “CPU registers” and read some stuff online.

I will extend my answer just for the sake of doing it.

OK, I copied your code and compiled it using GCC MinGW and disassembled it using objdump. Now here is the disassembly:

<sumofelements>:
0000000000000000 <sumofelements>:
   0:   55                      push   rbp
   1:   48 89 e5                mov    rbp,rsp
   4:   48 89 7d e8             mov    QWORD PTR [rbp-0x18],rdi
   8:   89 75 e4                mov    DWORD PTR [rbp-0x1c],esi
   b:   c7 45 f8 00 00 00 00    mov    DWORD PTR [rbp-0x8],0x0
  12:   c7 45 fc 00 00 00 00    mov    DWORD PTR [rbp-0x4],0x0
  19:   eb 1d                   jmp    38 <sumofelements+0x38>
  1b:   8b 45 fc                mov    eax,DWORD PTR [rbp-0x4]
  1e:   48 98                   cdqe
  20:   48 8d 14 85 00 00 00    lea    rdx,[rax*4+0x0]
  27:   00
  28:   48 8b 45 e8             mov    rax,QWORD PTR [rbp-0x18]
  2c:   48 01 d0                add    rax,rdx
  2f:   8b 00                   mov    eax,DWORD PTR [rax]
  31:   01 45 f8                add    DWORD PTR [rbp-0x8],eax
  34:   83 45 fc 01             add    DWORD PTR [rbp-0x4],0x1
  38:   8b 45 fc                mov    eax,DWORD PTR [rbp-0x4]
  3b:   3b 45 e4                cmp    eax,DWORD PTR [rbp-0x1c]
  3e:   7c db                   jl     1b <sumofelements+0x1b>
  40:   90                      nop
  41:   5d                      pop    rbp
  42:   c3                      ret

If you examine the disassembly you can see that the last modification of eax was at the 38th byte, after that the loop ends and we return. This line in particular

mov    eax,DWORD PTR [rbp-0x4]

is the line before the loop checks for i < size . The line moves [rbp-0x4] to eax . If we go back to the start of the program, we can see that [rbp-0x4] is i .

Considering all of this, everything makes sense. For the loop to end i < size must resolve to false . Since size is 8, i must also be 8 for the loop to end. The value of i is moved into eax to check if it smaller than size and at the iteration that the loop ends i would have the value of 8 and therefore eax would also be 8. The loop ends and we return what is in eax. So as a matter of fact it wasn't size in eax like my initial guess but it was rather i

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