| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2513 人关注过本帖
标题:函数 “调用” 只写函数名
只看楼主 加入收藏
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
这是编译器编译后的汇编代码:
 
; Listing generated by Microsoft (R) Optimizing Compiler Version 17.00.61030.0
 
    TITLE    C:\Users\TonyD_000\documents\visual studio 2012\Projects\test01\test2\main.cpp
    .686P
    .XMM
    include listing.inc
    .model    flat
 
INCLUDELIB MSVCRTD
INCLUDELIB OLDNAMES
 
PUBLIC    ?fun@@YAXH@Z                    ; fun
PUBLIC    _main
PUBLIC    ??_C@_03DPLIHHLN@?$CFd?0?$AA@            ; `string'
EXTRN    __imp__printf:PROC
EXTRN    __imp___getch:PROC
EXTRN    __RTC_CheckEsp:PROC
EXTRN    __RTC_InitBase:PROC
EXTRN    __RTC_Shutdown:PROC
;    COMDAT rtc$TMZ
rtc$TMZ    SEGMENT
__RTC_Shutdown.rtc$TMZ DD FLAT:__RTC_Shutdown
rtc$TMZ    ENDS
;    COMDAT rtc$IMZ
rtc$IMZ    SEGMENT
__RTC_InitBase.rtc$IMZ DD FLAT:__RTC_InitBase
rtc$IMZ    ENDS
;    COMDAT ??_C@_03DPLIHHLN@?$CFd?0?$AA@
CONST    SEGMENT
??_C@_03DPLIHHLN@?$CFd?0?$AA@ DB '%d,', 00H        ; `string'
CONST    ENDS
; Function compile flags: /Odtp /RTCsu /ZI
; File c:\users\tonyd_000\documents\visual studio 2012\projects\test01\test2\main.cpp
;    COMDAT _main
_TEXT    SEGMENT
_i$ = -8                        ; size = 4
_main    PROC                        ; COMDAT
 
; 10   : {
 
    push    ebp
    mov    ebp, esp
    sub    esp, 204                ; 000000ccH
    push    ebx
    push    esi
    push    edi
    lea    edi, DWORD PTR [ebp-204]
    mov    ecx, 51                    ; 00000033H
    mov    eax, -858993460                ; ccccccccH
    rep stosd
 
; 11   :     int i=5;
 
    mov    DWORD PTR _i$[ebp], 5
 
; 12   :     fun(i);
 
    mov    eax, DWORD PTR _i$[ebp]
    push    eax
    call    ?fun@@YAXH@Z                ; fun
    add    esp, 4
 
; 13   :     fun;
; 14   :     
; 15   :     _getch();
 
    mov    esi, esp
    call    DWORD PTR __imp___getch
    cmp    esi, esp
    call    __RTC_CheckEsp

 
; 16   : }
 
    xor    eax, eax
    pop    edi
    pop    esi
    pop    ebx
    add    esp, 204                ; 000000ccH
    cmp    ebp, esp
    call    __RTC_CheckEsp
    mov    esp, ebp
    pop    ebp
    ret    0

_main    ENDP
_TEXT    ENDS
; Function compile flags: /Odtp /RTCsu /ZI
; File c:\users\tonyd_000\documents\visual studio 2012\projects\test01\test2\main.cpp
;    COMDAT ?fun@@YAXH@Z
_TEXT    SEGMENT
_i$ = 8                            ; size = 4
?fun@@YAXH@Z PROC                    ; fun, COMDAT
 
; 5    : {
 
    push    ebp
    mov    ebp, esp
    sub    esp, 192                ; 000000c0H
    push    ebx
    push    esi
    push    edi
    lea    edi, DWORD PTR [ebp-192]
    mov    ecx, 48                    ; 00000030H
    mov    eax, -858993460                ; ccccccccH
    rep stosd
 
; 6    :     printf("%d,",i);
 
    mov    esi, esp
    mov    eax, DWORD PTR _i$[ebp]
    push    eax
    push    OFFSET ??_C@_03DPLIHHLN@?$CFd?0?$AA@
    call    DWORD PTR __imp__printf
    add    esp, 8
    cmp    esi, esp
    call    __RTC_CheckEsp
 
; 7    : }
 
    pop    edi
    pop    esi
    pop    ebx
    add    esp, 192                ; 000000c0H
    cmp    ebp, esp
    call    __RTC_CheckEsp
    mov    esp, ebp
    pop    ebp
    ret    0
?fun@@YAXH@Z ENDP                    ; fun
_TEXT    ENDS
END


可以看到源代码13、14、15行编译的结果,13行被直接忽略掉了。这是特定编译器的编译结果,对所有警告信息,如何处理,编译器有自由裁量权。你那公司用这种问题考你,根本就没有唯一答案,你反问他想要什么答案、谁会写出这种代码、是否他的公司以写这种代码为能事?

[ 本帖最后由 TonyDeng 于 2014-9-5 12:26 编辑 ]
收到的鲜花
  • 书生等待2014-09-05 22:39 送鲜花  5朵   附言:好文章

授人以渔,不授人以鱼。
2014-09-05 12:16
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
看看第16行的汇编结果,源代码是void main(),但汇编代码出来是带ret 0的。蓝色是整个收尾动作的汇编代码,它还call了一个函数,对应的源代码是一个空行,书呆子才把return 0看得那么重,你return 0之前该调用什么自己知道吗,干嘛不写?


[ 本帖最后由 TonyDeng 于 2014-9-5 12:29 编辑 ]

授人以渔,不授人以鱼。
2014-09-05 12:25
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
这个问题,也教训了我们另外一点,就是我经常说的“不要忽略编译警告”。你整行代码都已经被废掉了,当然运行时不会发生问题,但你如果并不知道这种代码是被废掉的,还自以为这样写没错,拿出去到处用,那只能害了自己。编程规范教导我们,把编译参数调整到最高级别(最起码也要3级),即把警告作错误对待,那么这种源代码就连编译都不能通过,迫使程序员去解决问题,让他彻底知道到底发生了什么事、而又是用什么方式解决的,否则他连出了事都不知道,别说很清楚自己程序的机制了,答辩时被人一问必然哑口无言。

授人以渔,不授人以鱼。
2014-09-05 12:57
Coincedence4
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:52
专家分:151
注 册:2014-9-4
收藏
得分:0 
回复 11 楼 书生等待
说错了,fun的地址是不能改变的,所以不能赋新的地址值。
你试试:printf("%p\n%d",fun,fun);输出的结果差异。可以看出fun就是个地址,不是调用。
2014-09-05 13:02
Coincedence4
Rank: 3Rank: 3
等 级:论坛游侠
帖 子:52
专家分:151
注 册:2014-9-4
收藏
得分:0 
回复 11 楼 书生等待
#include<stdio.h>
 int fun(int i)
 {
     printf("%d\n",i);
     return i;
 }

 void main()
 {
     int i=5;
     
     fun(i);
     fun;//因为不确定这个还是调用,标题加了引号...
     printf("%p\n%d\n%d",fun,fun,(*fun)(i));
     printf("\n");
     
     
 }
运行一下这个结果,你就知道fun是什么意思了。
2014-09-05 13:11
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
以下是引用TonyDeng在2014-9-5 12:25:21的发言:

看看第16行的汇编结果,源代码是void main(),但汇编代码出来是带ret 0的。蓝色是整个收尾动作的汇编代码,它还call了一个函数,对应的源代码是一个空行,书呆子才把return 0看得那么重,你return 0之前该调用什么自己知道吗,干嘛不写?
1. 汇编里面的ret 0和C语言里面的return 0;是完全不一样的东西 前者是平衡堆栈的 后者是返回值

2. 至于这个void 我理解的是 更确切的含义是这个函数的返回值没有含义
2014-09-05 13:24
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
回复 26 楼 zklhp
你喜欢怎么强调就怎么强调吧。

授人以渔,不授人以鱼。
2014-09-05 13:33
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
这是void main()的汇编代码:
 
; 16   : }
 
    xor    eax, eax
    pop    edi
    pop    esi
    pop    ebx
    add    esp, 204                ; 000000ccH
    cmp    ebp, esp
    call    __RTC_CheckEsp
    mov    esp, ebp
    pop    ebp
    ret    0


这是int main() {return 0;}的汇编码:
 
; 17   :     return 0;
 
    xor    eax, eax
 
; 18   : }
 
    pop    edi
    pop    esi
    pop    ebx
    add    esp, 204                ; 000000ccH
    cmp    ebp, esp
    call    __RTC_CheckEsp
    mov    esp, ebp
    pop    ebp
    ret    0


上10行,下10行,用比较程序比较一下两者有什么不同?

[ 本帖最后由 TonyDeng 于 2014-9-5 13:38 编辑 ]

授人以渔,不授人以鱼。
2014-09-05 13:36
zklhp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:china
等 级:贵宾
威 望:254
帖 子:11485
专家分:33241
注 册:2007-7-10
收藏
得分:0 
以下是引用TonyDeng在2014-9-5 13:36:36的发言:

这是void main()的汇编代码:
 
; 16   : }
 
    xor    eax, eax
    pop    edi
    pop    esi
    pop    ebx
    add    esp, 204                ; 000000ccH
    cmp    ebp, esp
    call    __RTC_CheckEsp
    mov    esp, ebp
    pop    ebp
    ret    0


这是int main() {return 0;}的汇编码:
 
; 17   :     return 0;
 
    xor    eax, eax
 
; 18   : }
 
    pop    edi
    pop    esi
    pop    ebx
    add    esp, 204                ; 000000ccH
    cmp    ebp, esp
    call    __RTC_CheckEsp
    mov    esp, ebp
    pop    ebp
    ret    0
我刚才想说 但打上了 又删掉了

最新的C语言标准提出了一个_Noreturn属性 这个东西能告诉编译器 这个函数不会返回 自然也就不会有你说的这些东西 当然了 至于微软大老爷支持不支持 我就不知道了
2014-09-05 13:40
书生等待
Rank: 7Rank: 7Rank: 7
等 级:黑侠
威 望:8
帖 子:280
专家分:689
注 册:2013-2-22
收藏
得分:0 
回复 20 楼 embed_xuel
额额,好吧
2014-09-05 22:42
快速回复:函数 “调用” 只写函数名
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017719 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved