为什么这段代码不适用于 -m32?

Why this code didn't work for -m32?

本文关键字:不适用 适用于 -m32 代码 段代码 为什么      更新时间:2023-10-16
#include <stddef.h>
template<size_t N = sizeof(void*)> struct a;
template<> struct a<4> {
    enum { b };
};
template<> struct a<8> {
    template<int> struct b {};
};
enum { c, d };
int main() {
    a<>::b<c>d;
    d;
}

我有一个代码,该代码可通过GCC成功编译X64架构。但是-m32失败,错误:

$ g++ -m32 test.cpp 
test.cpp: In function ‘int main()’:
test.cpp:16:12: warning: comparison between ‘enum a<4u>::<anonymous>’ and ‘enum<anonymous>’ [-Wenum-compare]
     a<>::b<c>d;
            ^
collect2: error: ld returned 1 exit status

此代码怎么了?

您的代码正确。显然,由于警告只是警告。它指出了以下事实:比较涉及两个无关的枚举,因此也许不明智。

如果您对分析感兴趣:
由于您要编译X86-32,因此sizeof(void*)为4。因此,a<>是指a<4>,随后a<4>::b是指枚举器。

所以表达式

a<>::b<c>d;

被解析为

(a<>::b < c) > d;

现在,使用积分促销的规则,将通常的算术转换进行了促进到int的情况。[expr.rel]/2:

通常在操作数上执行通常的算术转换 算术或枚举类型。[…]。转换后,操作数应具有相同的类型。

(注意稍后确保的粗体部分。)[expr]/10:

此模式称为通常的算术转换, 定义如下:

  • 如果任何一个操作数都是范围的枚举类型(7.2),则不会执行转换;如果另一个操作数没有相同的 类型,表达式不明显。
  • […关于浮点类型的子弹点……]
  • 否则,应在两个操作数上执行积分促销(4.5)。然后,以下规则应适用于 促进操作数:
    • 如果两个操作数具有相同的类型,则不需要进一步的转换。
    • […]

枚举者的积分促销涵盖了[Cons.Prom]/3:

一种未涉及的枚举类型的贵族,其基础类型不是 固定(7.2)可以转换为第一个的贵族 以下可以表示枚举的所有值的类型 (即,范围 b min to b max 中的值,如7.2中所述): intunsigned intlong intunsigned long intlong long intunsigned long long int

在将两个操作数晋升为int之后,该表达式的结果为false(因为0不小于0)。

然后将此促销的结果与d进行了比较 - 在此,如上所述,d被促进到int,而比较结果 - bool型的结果也促进了int。[cons.prom]/6:

bool类型的prvalue可以转换为 int类型 false变为零,true成为一个。

因此,这两个操作数具有int类型。第二个,外部比较得出true,因为false-> 0小于1,即d的值。

您的代码是没有错误的编译,实际错误在链接时发生。运行时库的链接器很可能无法找到 32位版本。您是否在系统上安装了它们?

相关文章: