当前位置: 首页 > 知识库问答 >
问题:

64位上的32位无符号乘法会导致未定义的行为吗?

程振濂
2023-03-14

所以我对这段代码有了一些了解:

uint32_t s1 = 0xFFFFFFFFU;
uint32_t s2 = 0xFFFFFFFFU;
uint32_t v;
...
v = s1 * s2; /* Only need the low 32 bits of the result */

在下面的所有内容中,我假设编译器不能对s1s2的范围有任何先入为主的概念,初始化器仅用于上面的示例。

如果我在一个32位的整数编译器上编译这个(比如在编译x86的时候),没问题。编译器会简单地使用s1s2作为uint32_t类型值(不能进一步提升它们),乘法会简单地给出注释所说的结果(模UINT_MAX1在这种情况下是0x100000000)。

然而,如果我在一个64位整数大小的编译器上编译这个(例如x86-64),从我可以从C标准中推断出的可能有未定义的行为。整数提升会看到uint32_t可以提升为int(64位有符号),乘法会尝试将两个int相乘,如果它们碰巧具有示例中显示的值,将导致整数溢出,这是未定义的行为。

我说的对吗?如果是的话,你会如何理智地避免它?

我发现了一个类似的问题,但涵盖了C:安全模乘无符号整数的最佳C方法是什么?。在这里,我想得到一个适用于C的答案(最好是C89兼容)。我不会考虑制造一个可怜的32位机器,它可能会执行一个64位乘法一个可接受的答案(通常在代码中,这将是值得关注的,32位的性能可能会更为关键,因为通常是那些较慢的机器)。

请注意,当使用32位int大小的编译器编译时,同样的问题也适用于16位无符号整数,或者当使用16位int大小的编译器编译时,同样的问题也适用于无符号字符(后者可能在8位CPU的编译器中很常见:C标准要求整数至少为16位,因此符合规范的编译器可能会受到影响)。

共有2个答案

周和安
2023-03-14

恭喜你找到了摩擦点。

一种可能的方式:

v = (uint32_t) (UINT_MAX<=0xffffffff
  ? s1 * s2
  : (unsigned)s1 * (unsigned)s2);

总之,看起来像是在

景鸿才
2023-03-14

要使乘法在至少为uint32_t且至少为unsigned int的无符号类型中发生,最简单的方法是使用类型为unsigned int的表达式。

v = 1U * s1 * s2;

这可以将1U转换为uint32_t,或者将s1s2转换为无符号int,具体取决于适合您的特定平台的内容。

@重复数据消除程序指出,某些编译器(其中uint32_t的范围小于unsigned int)可能会对赋值中的隐式转换发出警告,并指出,通过显式转换,此类警告可能会被抑制:

v = (uint32_t) (1U * s1 * S2);

不过,在我看来,它看起来不那么优雅。

 类似资料:
  • 我使用SIMD创建了一个64位*64位到128位的函数。目前我已经使用SSE2(实际上是SSE4.1)实现了它。这意味着它同时生产两个64b*64b到128b的产品。同样的想法可以扩展到AVX2或AVX512,同时提供四个或八个64b*64到128b的产品。我的算法基于http://www.hackersdelight.org/hdcodetxt/muldws.c.txt 该算法执行一次无符号乘法

  • 问题内容: 使用 应该以32位版本编译该文件。 不幸的是我得到这个错误: 我该如何解决? 如果我不使用它,则使用64位指令。 问题答案: 要在64位Linux版本上编译32位二进制文​​件,您必须安装开发包和32位GNU C库 尝试这个 和

  • 在使用java程序(带有Eclipse IDE)将leap motion listener从32位windows应用到64位windows后,该程序似乎运行正常。 问题是,现在与控制器的连接已初始化,已连接,然后在我不做任何操作的情况下立即退出。 我试着把手放在控制器上,结果出错了 Java运行时环境检测到一个致命错误: pc=0x000007fee8b4a975,pid=10516时的异常访问(

  • 我试图比较Peter Cordes在回答“将CPU寄存器中的所有位设置为1”的问题时提到的方法。 因此,我编写了一个基准测试,将所有13个寄存器设置为除、和之外的所有位1。 代码如下所示<代码>乘以32 nop用于避免DSB和LSD影响。 我测试了他提到的以下方法,以及这里的完整代码 为了使这个问题更简洁,我将使用替换下表中的。 下表显示,从组1到组3,当使用64位寄存器时,每个循环多1个周期。

  • 我有个奇怪的MSI!!!

  • 问题内容: 我已经使用Java一段时间了,而我典型的设置新开发机的习惯要求从Oracle站点下载并安装最新的JDK。 今天这引发了一个不寻常的问题, 回想起来,我已经安装了之前的两个版本,并且很高兴将普通的工具链插入(Eclipse)。在我的日常编程中,我不会回想起曾经因为使用64位JRE(或为此目的而针对64位JRE)而不得不以其他方式进行更改或思考的事情。 根据我对64位和32位的理解- 确实