C++ 来自cstdio和iostream的printf组装级别的差异
所以这个问题只是出于好奇。 我有一些小程序:C++ 来自cstdio和iostream的printf组装级别的差异,c++,c,io,C++,C,Io,所以这个问题只是出于好奇。 我有一些小程序: #include <some_header> void print(){ printf("abc"); } // don't care about main, I'm not gonna run it 它们之间有很大的区别,而且前三行是相同的,那么为什么iostream需要如此多的代码来清理,或者这些行只是在做什么?或者只是说,戈德博尔特在这个任务上是不可靠的 此外,标准似乎并不保证可以从iostream访问printf,这是否值得依
#include <some_header>
void print(){ printf("abc"); } // don't care about main, I'm not gonna run it
它们之间有很大的区别,而且前三行是相同的,那么为什么iostream
需要如此多的代码来清理,或者这些行只是在做什么?或者只是说,戈德博尔特在这个任务上是不可靠的
此外,标准似乎并不保证可以从
iostream
访问printf,这是否值得依赖?在这两种情况下,您的打印函数编译为几乎相同的汇编代码。
您看到的其他行是初始化和取消初始化iostream库。如果删除优化标志-O3
,您可能会清楚地看到这一点。
下面是包含iostream并关闭优化的完整列表
std::piecewise_construct:
.zero 1
.LC0:
.string "abc"
print():
pushq %rbp
movq %rsp, %rbp
movl $.LC0, %edi
movl $0, %eax
call printf
nop
popq %rbp
ret
__static_initialization_and_destruction_0(int, int):
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
cmpl $1, -4(%rbp)
jne .L4
cmpl $65535, -8(%rbp)
jne .L4
movl std::__ioinit, %edi
call std::ios_base::Init::Init()
movl $__dso_handle, %edx
movl std::__ioinit, %esi
movl std::ios_base::Init::~Init(), %edi
call __cxa_atexit
.L4:
nop
leave
ret
pushq %rbp
movq %rsp, %rbp
movl $65535, %esi
movl $1, %edi
call __static_initialization_and_destruction_0(int, int)
popq %rbp
ret
无论何时我包含
iostream
,这都是必须的吗?@YiFei这就是库的特定实现所做的。另一个实现的行为可能不同。C++标准没有指定这些实现细节。iostream
,那部分代码甚至存在于-Os
,所以我怀疑这是某种动态初始值设定项或类似的东西。
std::piecewise_construct:
.zero 1
.LC0:
.string "abc"
print():
pushq %rbp
movq %rsp, %rbp
movl $.LC0, %edi
movl $0, %eax
call printf
nop
popq %rbp
ret
__static_initialization_and_destruction_0(int, int):
pushq %rbp
movq %rsp, %rbp
subq $16, %rsp
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
cmpl $1, -4(%rbp)
jne .L4
cmpl $65535, -8(%rbp)
jne .L4
movl std::__ioinit, %edi
call std::ios_base::Init::Init()
movl $__dso_handle, %edx
movl std::__ioinit, %esi
movl std::ios_base::Init::~Init(), %edi
call __cxa_atexit
.L4:
nop
leave
ret
pushq %rbp
movq %rsp, %rbp
movl $65535, %esi
movl $1, %edi
call __static_initialization_and_destruction_0(int, int)
popq %rbp
ret