C++ 在编译器资源管理器上比较函数和函数模板之间的输出

C++ 在编译器资源管理器上比较函数和函数模板之间的输出,c++,gcc,output,c++17,compiler-explorer,C++,Gcc,Output,C++17,Compiler Explorer,我实现了阶乘函数的简单版本,两者都可以看到。我正在使用GCC主干。有两个源文件,第一个是函数版本,第二个是模板版本。每个源文件都有2个附带的编译器,并具有相关的输出。每个源文件的两个附加编译器之间的唯一区别是左侧编译器没有启用编译器标志或优化,而右侧版本将-O3设置为启用级别3优化 以下是我的职能: // Function Version int factorial(int n) { if (n == 0 || n == 1) return 1; if (n == 2) retu

我实现了阶乘函数的简单版本,两者都可以看到。我正在使用GCC主干。有两个源文件,第一个是函数版本,第二个是模板版本。每个源文件都有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;
}
资料来源2

一切都很好

所有四个程序执行返回值208

现在我的问题是:

但是,在第一个和第三个编译器的汇编程序中,如果不进行一些寄存器计算,这一点并不明显,但是在第二个和最后一个编译器中,在函数和模板版本都启用了-O3时,值720将在main的返回调用之前存储到EAX寄存器中。为什么编译器资源管理器显示:程序返回:208而不是720?

被定义为返回int。在main返回之后,C++运行时将调用STD::EXIT或等效代码,从main .< /p>返回的值。 还接受int退出代码。如何将此退出代码转换为流程返回代码由实现定义

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

<> Windows进程返回代码是32位有符号整数,因此直接传递给STD::EXT的int值。定义为:/P>< P>返回int。在main返回之后,C++运行时将调用STD::EXIT或等效代码,从main .< /P>返回的值。 还接受int退出代码。如何将此退出代码转换为流程返回代码由实现定义

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


在Windows上,进程返回码是32位有符号整数,因此直接返回传递给std::exit的int值。

main只能返回8位值-720%256=208@PaulR哦,好吧。。。是的,当我看着它的时候,我在想也许是十六进制,但七百二十进制不是二百零八。。。我不明白main只返回了一个字节。。。然而main的返回类型的函数声明是int,它应该是16、32或64位,这取决于体系结构和操作系统。。。我一直认为main的返回类型是int。我从来没有意识到要做模运算……是的,这是历史性的,因为main只返回一个状态码,我想人们觉得8位就足够了。@PaulR别误会,我很感谢你对缩小这种差异的反馈。。。我只是在那里摇头,想弄清楚如何、在何处以及为什么会产生这个值…main返回int,但是C++标准没有说明OS将使用多少比特。现在,POSIX只使用8位Windows使用32位,请参见main只能返回8位值-720%256=208@PaulR哦,好吧。。。是的,当我看着它的时候,我在想也许是十六进制,但七百二十进制不是二百零八。。。我不明白main只返回了一个字节。。。然而main的返回类型的函数声明是int,它应该是16、32或64位,这取决于体系结构和操作系统。。。我一直认为main的返回类型是int。我从来没有意识到要做模运算……是的,这是历史性的,因为main只返回一个状态码,我想人们觉得8位就足够了。@PaulR别误会,我很感谢你对缩小这种差异的反馈。。。我只是在那里摇头,想弄清楚如何、在何处以及为什么会产生这个值…main返回int,但是C++标准没有说明OS将使用多少比特。现在,POSIX只使用8位Windows使用32位,另请参阅未意识到main在GCC或Clang上只返回8位,而不是MSVC for Windows,我猜这是由于缺少使用Linux或其他POSIX Unix-BSD派生的操作系统造成的。。。95%的时间我都是专门为我的桌面使用Windows。我可能使用的POSIX的唯一变体是一些设备,如Android手机和电视设备盒,如Roku、类似Kodi的设备、亚马逊的FireTV棒或盒以及智能电视。。。然而,我并没有对它们进行太多编程,我只是使用它们的接口来使用它们…@FrancisCugler main总是返回一个int,如何将其转换为进程返回代码是特定于平台的,而不是特定于编译器的,例如,如果在windows上使用clang或gcc,您可能会得到32位退出代码结构。。。这是完全有道理的,因为这将归结为操作系统的系统调用……没有意识到main在GCC或Clang上只返回8位,而不是MSVC for Windows,我猜这是comi
由于没有使用Linux或其他POSIX Unix-BSD派生的操作系统而导致。。。95%的时间我都是专门为我的桌面使用Windows。我可能使用的POSIX的唯一变体是一些设备,如Android手机和电视设备盒,如Roku、类似Kodi的设备、亚马逊的FireTV棒或盒以及智能电视。。。然而,我并没有对它们进行太多编程,我只是使用它们的接口来使用它们…@FrancisCugler main总是返回一个int,如何将其转换为进程返回代码是特定于平台的,而不是特定于编译器的,例如,如果在windows上使用clang或gcc,您可能会得到32位退出代码结构。。。这是完全有道理的,因为这将归结为操作系统的系统调用。。。
int main() {
    return factorial(6);
}
int main() {
    return factorial_t<6>();
}
         |   Assembly Instruction Count   |
Type     | Without O3 | With O3 Turned On |  
Function |     34     |       29          |
Template |     50     |        3          |