在Compiler Explorer中比较函数和函数模板之间的输出



我实现了阶乘函数的简单版本,它们都可以在这里看到。我正在使用GCC Trunk。有2个源文件,第一个是函数版本,第二个是模板版本。每个源文件都有2个附带的编译器和相关的输出。每个源文件附带的两个编译器之间的唯一区别是,左边的编译器没有编译器标志或优化打开,而右边的版本有-O3设置为打开3级优化。

下面是我的函数:

// Function Version
int factorial(int n) {
if (n == 0 || n == 1) return 1;
if (n == 2) return 2;
return (n * factorial(n-1));
}
// Template Version:
template<unsigned N>
static auto constexpr factorial_t() {
return (N * factorial<N-1>());
}
template<>
auto constexpr factorial_t<0>() {
return 1;
}
template<>
auto constexpr factorial_t<1>() {
return 1;
}
template<>
auto constexpr factorial_t<2>() {
return 2;
}

现在,当我在本地PC上使用c++17在我安装的IDEVisual Studio 2017中运行这些时,我得到了从main()返回的预期输出,并且返回值对于两个实现都是正确的。

我将它移植到编译器资源管理器,以测试其他编译器和它们的优化,以比较它们生成的汇编指令。这是一个相当简单的过程。

现在当我像这样运行这些函数时:

源# 1

int main() {
return factorial(6);
}

源# 2

int main() {
return factorial_t<6>();
}

编译器资源管理器生成以下指令计数…

  • |   Assembly Instruction Count   |
    
  • Type     | Without O3 | With O3 Turned On |  
    
  • Function |     34     |       29          |
    
  • Template |     50     |        3          |
    

一切都好。

所有四次程序执行都返回值208

现在回答我的问题:

然而,在没有做一些寄存器数学的情况下,在第一个和第三个编译器的汇编中并不明显,但是在第二个和最后一个functiontemplate版本都打开-O3的情况下,值720main()返回调用之前被存储到EAX寄存器中。为什么编译器资源管理器显示:Program returned: 208而不是720?

main被定义为返回int。在main返回后,c++运行时将使用main返回的值调用std::exit(或等效代码)。

std::exit也接受int退出码。如何将退出码转换为进程返回码由实现定义。

在Unix上,进程的返回码通常是一个无符号字节,因此int被简单地截断以适合0-255

在Windows上进程返回码是32位有符号整数,所以传递给std::exitint值直接返回。

最新更新