微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么来自 MSYS2 的 GNU MP (gmplib) 意外地将 ull 转换为 32 位整数?

如何解决为什么来自 MSYS2 的 GNU MP (gmplib) 意外地将 ull 转换为 32 位整数?

我正在使用 MSYS2(64 位)将我的 C++ 代码从 Linux 移植到 Windows。关键库是 GNU MP (gmplib)。以下代码在 MSYS2/MinGW64 环境中给出了错误的结果,而在 Ubuntu 中工作正常。显然,在使用 mpz_set_ui 函数时,会发生从 64 位整数到 32 位非整数的不必要的转换。

#include <iostream>
    #include <gmp.h>  
    int main() {
        std::cout << "GMP version: " << __gmp_version << std::endl;
        std::cout << "GMP_LIMB_BITS: " << GMP_LIMB_BITS << std::endl;
    
        unsigned long long a = UINT64_MAX; 
        std::cout << a << std::endl;
    
        mpz_t mpz;
        mpz_init(mpz);
        mpz_set_ui(mpz,a);
    
        unsigned long long b = mpz_get_ui(mpz);
        std::cout << b << std::endl;
    }

Ubuntu 正确输出

GMP version: 6.2.0
GMP_LIMB_BITS: 64
18446744073709551615
18446744073709551615

MSYS2/MinGW64 意外转换:

GMP version: 6.2.1
GMP_LIMB_BITS: 64
18446744073709551615
4294967295

重现行为的步骤:

  1. 全新安装 MSYS2(64 位)。
  2. 来自 https://www.msys2.org/Getting Started 的步骤在 MSYS2 环境中运行:

pacman -Syu

pacman -Su

pacman -S --needed base-devel mingw-w64-x86_64-toolchain

  1. 使用静态链接在 MinGW64 环境中编译:
g++ -MT .o/main.o -MD -MP -MF .d/main.Td -std=c++17 -g -Wall -Wextra -pedantic -c -o .o/main.o main.cpp

mv -f .d/main.Td .d/main.d

g++ -static -o main .o/main.o -lgmp

main.d 按预期指向 C:/msys64/mingw64/include/gmp.h,我确认 C:\msys64\mingw64\lib\libgmp.a 用于链接,没有其他版本的 gmplib.a存在于 C:/msys64

的子文件夹中

我还使用以下方法定制了 GNU MP 库:

./configure

制作

进行安装

然而,不需要的转换还是一样。我可能会错过一些基本的东西,但我不知所措。这是我关于 Stackoverflow 的第一个问题,非常感谢您的帮助。

解决方法

mpz_get_ui() 函数返回 unsigned long,而不是 unsigned long long

在 Linux/GCC 上,unsigned long 是一个 64 位值,但是 C++ 标准只要求 unsigned long 支持高达 4'294'967'295 的值,这可以通过 32-位整数。 Linux 允许更大的值,但 Windows 上的 MSVC 和 MinGW 将对 unsigned long 使用 32 位整数。这意味着在 Windows 上,mps_set_ui() 中的 64 位输入值会降级为 32 位值。

因此,两个编译器上的行为都是正确的,您遇到了特定于平台的实现细节。

如果您希望允许在任何地方使用 64 位整数,您应该使用固定位宽的整数类型(例如 uint64_t 而不是 unsigned long),但这仍然不允许您不幸的是,在 Windows 上指定 64 位整数 mp_set_ui

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。