glassy @ 2019-11-12 13:34:17
校内的模拟赛遇到了这样的题面
本题可能涉及到大量输入,请妥善选择输入方式。对于C++,一个简单有效的方式是使用stdio.h 文件下的输入而非cstdio;VC++则不需要考虑这一点。
然后实测也确实快了(近乎一倍)。
蒟蒻如何想也不清楚为什么会有区别,因为在cstdio
的定义中有这样一句话
#ifdef _STD_USING
#undef _STD_USING
#include <stdio.h>
#define _STD_USING
#else /* _STD_USING */
#include <stdio.h>
#endif /* _STD_USING */
所以理论上不管有没有定义_STD_USING
,cstdio
是包含了stdio.h
的。
为了弄清楚到底为什么,蒟蒻尝试观察它们的汇编代码,结果,两者的汇编代码几乎完全一致(唯一的不同是两者的文件名称) 源代码如下:
//stdio.cpp
#include<stdio.h>
int main(){
int n;
scanf("%d",&n);
}
//cstdio.cpp
#include<cstdio>
int main(){
int n;
scanf("%d",&n);
}
汇编代码如下
.file "stdio.cpp"
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "%d\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB8:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
call ___main
leal 28(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _scanf
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE8:
.ident "GCC: (GNU) 4.8.1"
.def _scanf; .scl 2; .type 32; .endef
.file "cstdio.cpp"
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "%d\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
LFB8:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
call ___main
leal 28(%esp), %eax
movl %eax, 4(%esp)
movl $LC0, (%esp)
call _scanf
movl $0, %eax
leave
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
LFE8:
.ident "GCC: (GNU) 4.8.1"
.def _scanf; .scl 2; .type 32; .endef
经比对几乎完全一致,然而编译出的exe文件大小却不一样。
stdio.exe:102KB
cstdio.exe:109KB
蒟蒻想问一下它们效率到底差在哪里了,以及为何同一份汇编代码会得到不同的机器代码。
感激不尽。
by tiger0133 @ 2019-11-12 13:34:45
有意思的问题,铜球
by WYXkk @ 2019-11-12 13:35:54
有意思,但是我看不懂汇编
by _H1kar1 @ 2019-11-12 13:36:31
有意思的问题,铜球qwq
by zl_just @ 2019-11-12 13:37:17
有意思的问题,所以我选择快读
by glassy @ 2019-11-12 13:37:21
我也看不懂汇编QAQ,只看着完全一样……
by 木木! @ 2019-11-12 13:40:22
不知道为什么,我这里编译并 fc 是有差距的(
要说什么影响的话,估计是全局变量的构造和析构带来的影响(
by 木木! @ 2019-11-12 13:41:36
by StudyingFather @ 2019-11-12 13:43:09
@glassy
预编译指令 `include` 将会把要包含的文件直接复制到相应位置,也就是说 `#include <cstdio>` 将会直接将 `cstdio` 的内容复制到源文件的开头位置。
因此编译出来的文件大小会有差别。
by StudyingFather @ 2019-11-12 13:43:38
(别问我为啥要全用代码框框起来,因为不这么框就发不出去
by 倍镜 @ 2019-11-12 13:43:56
我个蒟蒻看不懂T_T
@glassy 还说自己蒟蒻