[英]Why does this function not return a value of 1 when I modify a character array in a separate else statement?
[英]Why does this function returns size of array when there is no return statement?
对于这个程序,我得到 output 作为 8。 为什么这个 function 在没有 return 语句的情况下返回数组的大小? 当我写返回语句时它工作正常,但我仍然很好奇为什么这个 function 返回数组的大小。 我认为它应该返回垃圾值。
#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);
}
行为未定义。 任何值都是可能的,包括观察到的行为。 在一些奇特的架构上,陷阱值可能会导致其他奇怪的行为。
对于您的特定情况, main
期望sumofelements
放置其返回值(某些 CPU 寄存器)的位置恰好包含size
的值,但不能保证:它可能不在不同的 CPU/OS/编译器组合上/一组选项/一天中的时间...
使用gcc -Wall -Werror
或类似的警告级别来避免此类愚蠢的错误。
您可以在Godbolt 的编译器资源管理器上查看程序集和行为,并使用编译器标志和编译器版本来了解行为的易变性。 使用-O2
, gcc和clang 都为 sumofelements生成一个简单的ret
指令,甚至不为sumofelements
调用调用这个printf
。
未明确从非空 function( main()
除外)返回值会导致未定义的行为。 这意味着任何事情都可能发生:崩溃、返回垃圾值,或者更糟糕的是,返回预期值!
您应该始终从非空 function 返回一些(有意义的)东西。
返回值是从eax
中选取的,它是你 CPU 上的一个寄存器(寄存器就像你的 CPU 自己在 RAM 之外存储一些少量数据的地方)它恰好是 function 结束之前eax
包含数组的大小。
可能在i < size
中, size
存储在eax
中,并且在您的 function 结束之前不会进一步修改,但是您必须objdump -d
您的程序并将其粘贴到此处,以便我说出任何确定的内容。
如果您想了解更多信息,请输入“CPU registers”并在线阅读一些内容。
为了这样做,我将扩展我的答案。
好的,我复制了你的代码并使用 GCC MinGW 编译它并使用 objdump 反汇编它。 现在这里是反汇编:
<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
如果你检查反汇编,你可以看到eax
的最后修改是在第 38 个字节,之后循环结束,我们返回。 特别是这条线
mov eax,DWORD PTR [rbp-0x4]
是循环检查i < size
之前的行。 该行将[rbp-0x4]
移动到eax
。 如果我们 go 回到程序的开头,我们可以看到[rbp-0x4]
是i
。
考虑到所有这些,一切都是有道理的。 要使循环结束, i < size
必须解析为false
。 由于size
为 8,因此i
也必须为 8 才能结束循环。 i
的值被移入eax
以检查它是否小于size
并且在循环结束的迭代中i
的值将是 8,因此eax
也将是 8。循环结束并且我们返回 eax 中的内容。 所以事实上它并不像我最初猜测的那样是eax
的大小,而是i
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.