user-0 提问: 关于Return的问题。

回复:
user: user-1
content: 引用 13 楼 weixin_45358177的回复:[quote=引用 12 楼 ggglivw的回复:]add (int Long,int Width) 没有return 嗯，我知道自己没打return，我是在去掉return的条件下看它有什么作用。说概念的话我知道它是返回，也知道它可以接受也可以不接受，但对于不打return出来的奇怪结果我想知道系统是怎么运行的。 还有return 在运行过程中对最后的结果有什么作用。[/quote] iResult=add(m_Long,m_Width);这句话就不成立，add没有返回值，你还定义变量来接受它，岂不是矛盾。

user: user-2
content: 代码贴出来.

user: user-0
content: 引用 21 楼 636f6c696e的回复:原来以为这样的程序编译不过的，但在gcc上试了下居然还真能编过，所以顺带分析了下 (gdb) disassemble  add Dump of assembler code for function add:    0x0000000000400674 <+0>:     push   %rbp    0x0000000000400675 <+1>:     mov    %rsp,%rbp    0x0000000000400678 <+4>:     sub    $0x20,%rsp    0x000000000040067c <+8>:     mov    %edi,-0x14(%rbp)    0x000000000040067f <+11>:    mov    %esi,-0x18(%rbp)    0x0000000000400682 <+14>:    mov    -0x14(%rbp),%eax    0x0000000000400685 <+17>:    mov    %eax,%edx    0x0000000000400687 <+19>:    imul   -0x18(%rbp),%edx    0x000000000040068b <+23>:    mov    %edx,%eax    0x000000000040068d <+25>:    shl    $0x2,%eax    0x0000000000400690 <+28>:    add    %edx,%eax    0x0000000000400692 <+30>:    add    %eax,%eax    0x0000000000400694 <+32>:    mov    %eax,-0x4(%rbp)    0x0000000000400697 <+35>:    mov    -0x4(%rbp),%esi    0x000000000040069a <+38>:    mov    $0x4007e5,%edi    0x000000000040069f <+43>:    mov    $0x0,%eax    0x00000000004006a4 <+48>:    callq  0x4004e0 <printf@plt>    0x00000000004006a9 <+53>:    leaveq     0x00000000004006aa <+54>:    retq   简单解释下，函数的返回值都是保存在寄存器eax上的，我们可以看到add函数在return之前， 先将寄存器eax赋值为0：mov    $0x0,%eax 然后再调用printf函数：callq  0x4004e0 <printf@plt> 之后就返回了：leaveq 、retq 因此返回值实质上就是printf的返回值。  可能很多人不知道prinf这个函数是有返回值的，返回值代表实际输出字符的长度。 printf("长方体的体积为：%d\n"， iResult); 中“长方体的体积为：”都是中文字符，每个2个字节，一共是16字节。 %d是体积，如果输入是1 2，体积是20，那么就是2个字节，再加上\n 1个字节，加起来就是19字节，所以输出是19. 如果你输入的是1 10，那么体积是100，输出则会是20。  不过说了那么多，这些东西对初学者并无实际的意义。正确的做法是显示指定返回值，知道这点就够了。 [quote=引用 13 楼 weixin_45358177 的回复:] [quote=引用 12 楼 ggglivw的回复:]add (int Long,int Width) 没有return 嗯，我知道自己没打return，我是在去掉return的条件下看它有什么作用。说概念的话我知道它是返回，也知道它可以接受也可以不接受，但对于不打return出来的奇怪结果我想知道系统是怎么运行的。 还有return 在运行过程中对最后的结果有什么作用。[/quote][/quote] 因为我们 高中物理化学学的有效数字 是从左边第一个不为零的数字开始算。所以我们是区分有效数字几位和小数点后几位（从小数点后第一位开始算，不同于 有效数字的概念）这两个概念的。但我最近感觉 有关资料上认为这两个概念是等价的。

user: user-0
content: 引用 21 楼 636f6c696e的回复:原来以为这样的程序编译不过的，但在gcc上试了下居然还真能编过，所以顺带分析了下 (gdb) disassemble  add Dump of assembler code for function add:    0x0000000000400674 <+0>:     push   %rbp    0x0000000000400675 <+1>:     mov    %rsp,%rbp    0x0000000000400678 <+4>:     sub    $0x20,%rsp    0x000000000040067c <+8>:     mov    %edi,-0x14(%rbp)    0x000000000040067f <+11>:    mov    %esi,-0x18(%rbp)    0x0000000000400682 <+14>:    mov    -0x14(%rbp),%eax    0x0000000000400685 <+17>:    mov    %eax,%edx    0x0000000000400687 <+19>:    imul   -0x18(%rbp),%edx    0x000000000040068b <+23>:    mov    %edx,%eax    0x000000000040068d <+25>:    shl    $0x2,%eax    0x0000000000400690 <+28>:    add    %edx,%eax    0x0000000000400692 <+30>:    add    %eax,%eax    0x0000000000400694 <+32>:    mov    %eax,-0x4(%rbp)    0x0000000000400697 <+35>:    mov    -0x4(%rbp),%esi    0x000000000040069a <+38>:    mov    $0x4007e5,%edi    0x000000000040069f <+43>:    mov    $0x0,%eax    0x00000000004006a4 <+48>:    callq  0x4004e0 <printf@plt>    0x00000000004006a9 <+53>:    leaveq     0x00000000004006aa <+54>:    retq   简单解释下，函数的返回值都是保存在寄存器eax上的，我们可以看到add函数在return之前， 先将寄存器eax赋值为0：mov    $0x0,%eax 然后再调用printf函数：callq  0x4004e0 <printf@plt> 之后就返回了：leaveq 、retq 因此返回值实质上就是printf的返回值。  可能很多人不知道prinf这个函数是有返回值的，返回值代表实际输出字符的长度。 printf("长方体的体积为：%d\n"， iResult); 中“长方体的体积为：”都是中文字符，每个2个字节，一共是16字节。 %d是体积，如果输入是1 2，体积是20，那么就是2个字节，再加上\n 1个字节，加起来就是19字节，所以输出是19. 如果你输入的是1 10，那么体积是100，输出则会是20。  不过说了那么多，这些东西对初学者并无实际的意义。正确的做法是显示指定返回值，知道这点就够了。 [quote=引用 13 楼 weixin_45358177 的回复:] [quote=引用 12 楼 ggglivw的回复:]add (int Long,int Width) 没有return 嗯，我知道自己没打return，我是在去掉return的条件下看它有什么作用。说概念的话我知道它是返回，也知道它可以接受也可以不接受，但对于不打return出来的奇怪结果我想知道系统是怎么运行的。 还有return 在运行过程中对最后的结果有什么作用。[/quote][/quote] 分数用完了，好像不能发帖提问了。所以这里问一下吧：一般说的float和double有效数字6位和15位是指小数点后的6位和15位吧？

user: user-0
content: 引用 21 楼 636f6c696e的回复:原来以为这样的程序编译不过的，但在gcc上试了下居然还真能编过，所以顺带分析了下 (gdb) disassemble  add Dump of assembler code for function add:    0x0000000000400674 <+0>:     push   %rbp    0x0000000000400675 <+1>:     mov    %rsp,%rbp    0x0000000000400678 <+4>:     sub    $0x20,%rsp    0x000000000040067c <+8>:     mov    %edi,-0x14(%rbp)    0x000000000040067f <+11>:    mov    %esi,-0x18(%rbp)    0x0000000000400682 <+14>:    mov    -0x14(%rbp),%eax    0x0000000000400685 <+17>:    mov    %eax,%edx    0x0000000000400687 <+19>:    imul   -0x18(%rbp),%edx    0x000000000040068b <+23>:    mov    %edx,%eax    0x000000000040068d <+25>:    shl    $0x2,%eax    0x0000000000400690 <+28>:    add    %edx,%eax    0x0000000000400692 <+30>:    add    %eax,%eax    0x0000000000400694 <+32>:    mov    %eax,-0x4(%rbp)    0x0000000000400697 <+35>:    mov    -0x4(%rbp),%esi    0x000000000040069a <+38>:    mov    $0x4007e5,%edi    0x000000000040069f <+43>:    mov    $0x0,%eax    0x00000000004006a4 <+48>:    callq  0x4004e0 <printf@plt>    0x00000000004006a9 <+53>:    leaveq     0x00000000004006aa <+54>:    retq   简单解释下，函数的返回值都是保存在寄存器eax上的，我们可以看到add函数在return之前， 先将寄存器eax赋值为0：mov    $0x0,%eax 然后再调用printf函数：callq  0x4004e0 <printf@plt> 之后就返回了：leaveq 、retq 因此返回值实质上就是printf的返回值。  可能很多人不知道prinf这个函数是有返回值的，返回值代表实际输出字符的长度。 printf("长方体的体积为：%d\n"， iResult); 中“长方体的体积为：”都是中文字符，每个2个字节，一共是16字节。 %d是体积，如果输入是1 2，体积是20，那么就是2个字节，再加上\n 1个字节，加起来就是19字节，所以输出是19. 如果你输入的是1 10，那么体积是100，输出则会是20。  不过说了那么多，这些东西对初学者并无实际的意义。正确的做法是显示指定返回值，知道这点就够了。 [quote=引用 13 楼 weixin_45358177 的回复:] [quote=引用 12 楼 ggglivw的回复:]add (int Long,int Width) 没有return 嗯，我知道自己没打return，我是在去掉return的条件下看它有什么作用。说概念的话我知道它是返回，也知道它可以接受也可以不接受，但对于不打return出来的奇怪结果我想知道系统是怎么运行的。 还有return 在运行过程中对最后的结果有什么作用。[/quote][/quote] 谢谢你的分析和解释，现在知道结果异常的原因了。

user: user-3
content: 原来以为这样的程序编译不过的，但在gcc上试了下居然还真能编过，所以顺带分析了下 (gdb) disassemble  add Dump of assembler code for function add:    0x0000000000400674 <+0>:     push   %rbp    0x0000000000400675 <+1>:     mov    %rsp,%rbp    0x0000000000400678 <+4>:     sub    $0x20,%rsp    0x000000000040067c <+8>:     mov    %edi,-0x14(%rbp)    0x000000000040067f <+11>:    mov    %esi,-0x18(%rbp)    0x0000000000400682 <+14>:    mov    -0x14(%rbp),%eax    0x0000000000400685 <+17>:    mov    %eax,%edx    0x0000000000400687 <+19>:    imul   -0x18(%rbp),%edx    0x000000000040068b <+23>:    mov    %edx,%eax    0x000000000040068d <+25>:    shl    $0x2,%eax    0x0000000000400690 <+28>:    add    %edx,%eax    0x0000000000400692 <+30>:    add    %eax,%eax    0x0000000000400694 <+32>:    mov    %eax,-0x4(%rbp)    0x0000000000400697 <+35>:    mov    -0x4(%rbp),%esi    0x000000000040069a <+38>:    mov    $0x4007e5,%edi    0x000000000040069f <+43>:    mov    $0x0,%eax    0x00000000004006a4 <+48>:    callq  0x4004e0 <printf@plt>    0x00000000004006a9 <+53>:    leaveq     0x00000000004006aa <+54>:    retq   简单解释下，函数的返回值都是保存在寄存器eax上的，我们可以看到add函数在return之前， 先将寄存器eax赋值为0：mov    $0x0,%eax 然后再调用printf函数：callq  0x4004e0 <printf@plt> 之后就返回了：leaveq 、retq 因此返回值实质上就是printf的返回值。  可能很多人不知道prinf这个函数是有返回值的，返回值代表实际输出字符的长度。 printf("长方体的体积为：%d\n"， iResult); 中“长方体的体积为：”都是中文字符，每个2个字节，一共是16字节。 %d是体积，如果输入是1 2，体积是20，那么就是2个字节，再加上\n 1个字节，加起来就是19字节，所以输出是19. 如果你输入的是1 10，那么体积是100，输出则会是20。  不过说了那么多，这些东西对初学者并无实际的意义。正确的做法是显示指定返回值，知道这点就够了。 引用 13 楼 weixin_45358177 的回复:[quote=引用 12 楼 ggglivw的回复:]add (int Long,int Width) 没有return 嗯，我知道自己没打return，我是在去掉return的条件下看它有什么作用。说概念的话我知道它是返回，也知道它可以接受也可以不接受，但对于不打return出来的奇怪结果我想知道系统是怎么运行的。 还有return 在运行过程中对最后的结果有什么作用。[/quote]

user: user-4
content: 现在编程越来越傻瓜式了，居然这么写也是符合语法规则的

user: user-0
content: 引用 19 楼 WNs_ACE的回复:补充一下，每个函数结束的时候，不管有没有return，都会调用ret指令（有时候会使用jmp或者其他跳转指令和push指令配合使用达到ret指令的效果，具体可能需要看具体的编译器来定，没有办法一概而论） 谢谢！实在没有别的感激的话了。

user: user-5
content: 补充一下，每个函数结束的时候，不管有没有return，都会调用ret指令（有时候会使用jmp或者其他跳转指令和push指令配合使用达到ret指令的效果，具体可能需要看具体的编译器来定，没有办法一概而论）

user: user-5
content: 你这个程序可能只能在高版本的vs上面编译了，低版本的vs都可以编译不了，而你要理解一个东西，return在汇编其实就是ret，而ret指令的作用就是出栈和把栈顶地址交给EIP寄存器，然后把EAX寄存器的东西作为函数返回值赋值给iResult变量，其实你上面的程序不管你写不写return，最后都会把EXA寄存器的东西交给iResult变量，至于EAX寄存器到底放什么的数据，就要看编译器编译出来的汇编逻辑来决定了，所以你看到的“少1的普遍规律”可能只是运气和编译器版本导致的，想要了解语法的底层，你最好还是去看汇编指令才容易明白。

user: user-6
content: 语法规定的，你应该返回，你不返回编译器通过后会产生啥后果你只有去看编译器的实现了。这种在古老的编译器上是无法通过编译的

user: user-0
content: 引用 12 楼 ggglivw的回复:add (int Long,int Width) 没有return 嗯，我知道自己没打return，我是在去掉return的条件下看它有什么作用。说概念的话我知道它是返回，也知道它可以接受也可以不接受，但对于不打return出来的奇怪结果我想知道系统是怎么运行的。 还有return 在运行过程中对最后的结果有什么作用。

user: user-6
content: add (int Long,int Width) 没有return

user: user-0
content: 引用 6 楼 ggglivw 的回复:你准备让我手敲你代码给你分析？我无偿给你回答问题还要自己手敲，你觉得谁会这么干. 谢谢啦，不是贴的，教室没网，到老师办公室敲得。 这个add（）没有return。 #include<stdio.h> #include<stdlib.h> #define Height 10  int add(int Long,int Width); int main() { int m_Long; int m_Width; int iResult; printf(“请输入长方体的长：”）； scanf("%d",&m_Long); printf("请输入长方体的宽："); scanf("%d",&m_Width); iResult=add(m_Long,m_Width); printf("长方体的体积为：%d\n",iResult); system("pause"); } add (int Long,int Width) { int iResult=Long*Width*Height; printf("长方体的体积为：%d"iResult); }

user: user-0
content: 引用 9 楼 轻箬笠的回复:[quote=引用 8 楼 weixin_45358177 的回复:] [quote=引用 6 楼 ggglivw的回复:]你准备让我手敲你代码给你分析？我无偿给你回答问题还要自己手敲，你觉得谁会这么干. 前辈，“代码贴出来”的意思是敲到这个论坛里吗？对不起，新人不太了解了 。我觉得自己已经拍下来了呀。[/quote] 程序不跑一下，有些问题查不出来。那怎么跑呢？你是拍下了，回答问题的人是对着照片再写一遍代码，还是有软件可以让回答问题的人自动识别照片里面的代码？[/quote] 谢谢你，        明白了。

user: user-7
content: 引用 8 楼 weixin_45358177 的回复:[quote=引用 6 楼 ggglivw的回复:]你准备让我手敲你代码给你分析？我无偿给你回答问题还要自己手敲，你觉得谁会这么干. 前辈，“代码贴出来”的意思是敲到这个论坛里吗？对不起，新人不太了解了 。我觉得自己已经拍下来了呀。[/quote] 程序不跑一下，有些问题查不出来。那怎么跑呢？你是拍下了，回答问题的人是对着照片再写一遍代码，还是有软件可以让回答问题的人自动识别照片里面的代码？

user: user-0
content: 引用 6 楼 ggglivw的回复:你准备让我手敲你代码给你分析？我无偿给你回答问题还要自己手敲，你觉得谁会这么干. 前辈，“代码贴出来”的意思是敲到这个论坛里吗？对不起，新人不太了解了 。我觉得自己已经拍下来了呀。

user: user-6
content: 自己看3楼的回答，他已经说清楚原因了，编译器版本的设置不同，某些错误会给你报警告，本来你应该是编译不过的，结果弄了一个警告出来。

user: user-6
content: 你准备让我手敲你代码给你分析？我无偿给你回答问题还要自己手敲，你觉得谁会这么干.

user: user-0
content: 引用 2 楼 ggglivw的回复:代码贴出来. 前辈，照片上的不算代码吗？