在64位导致未定义行为的32位无符号乘法? [英] 32 bit unsigned multiply on 64 bit causing undefined behavior?

查看:179
本文介绍了在64位导致未定义行为的32位无符号乘法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我对这个code:

So I have about this code:

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

在所有的以下我假定编译器不能对 S1 S2 时,初始化只提供上面的例子。

In all the followings I assume the compiler couldn't have any preconceptions on the range of s1 or s2, the initializers only serving for an example above.

如果我编译这与32位整数大小编译器(例如用于x86编译时),没有问题。编译器会简单地使用 S1 S2 uint32_t的键入值(不能够进一步促进它们),和乘法会简单地给结果作为评论说,(模 UINT_MAX + 1 这是0x100000000这种情况下)。

If I compiled this on a compiler with an integer size of 32 bits (such as when compiling for x86), no problem. The compiler would simply use s1 and s2 as uint32_t typed values (not being able to promote them further), and the multiplication would simply give the result as the comment says (modulo UINT_MAX + 1 which is 0x100000000 this case).

但是,如果我有64位(如X86-64)整数大小编译这对一个编译器,有可能是从我可以从C标准推导出不确定的行为。整型提升将看到 uint32_t的可以晋升到 INT (64位有符号),乘法会然后尝试将两个的, INT ,如果他们碰巧在这个例子中显示的值,将导致整数溢出,这是不确定的行为。

However if I compiled this on a compiler with an integer size of 64 bits (such as for x86-64), there might be undefined behavior from what I can deduce from the C standard. Integer promotion would see uint32_t can be promoted to int (64 bit signed), the multiplication would then attempt to multiply two int's, which, if they happen to have the values shown in the example, would cause an integer overflow, which is undefined behavior.

我是这个改正,如果是的话你会怎么避免它在一个正常的方式?

Am I correct with this and if so how would you avoid it in a sane way?

我发现这个问题,这是类似的,但包括C ++:<一href=\"http://stackoverflow.com/questions/24795651/whats-the-best-c-way-to-multiply-unsigned-integers-modularly-safely\">What's最好的C ++的方式繁殖无符号整数模块化安全?。在这里,我想获得适用到C答案(preferably C89兼容)。我不会考虑做一个可怜的32位的机器可能执行的64位乘以虽然一个可以接受的答案(通常在code其中这将是一个问题,因为通常这些都是较慢的机器32位的性能可能更严重)

I spotted this question which is similar, but covers C++: What's the best C++ way to multiply unsigned integers modularly safely?. Here I would like to get an answer applicable to C (preferably C89 compatible). I wouldn't consider making a poor 32 bit machine potentially executing a 64 bit multiply an acceptable answer though (usually in code where this would be of concern, 32 bit performance might be more critical as typically those are the slower machines).

请注意,当与当用具有16位的int大小一编译器编译的具有32位的int大小,或无符号字符一个编译器编译同样的问题可以应用到16位无符号整数(后者可能是共同与编译器8位CPU:C标准要求整数至少为16位,因此编译器一致,很可能受到影响)

Note that the same problem can apply to 16 bit unsigned ints when compiled with a compiler having a 32 bit int size, or unsigned chars when compiled with a compiler having a 16 bit int size (the latter might be common with compilers for 8 bit CPUs: the C standard requires integers to be at least 16 bits, so a conforming compiler is likely affected).

推荐答案

要获得乘法无符号类型是发生最简单的方法,至少 uint32_t的,和至少也在 unsigned int类型,是涉及类型的前pression unsigned int类型

The simplest way to get the multiplication to happen in an unsigned type that is at least uint32_t, and also at least unsigned int, is to involve an expression of type unsigned int.

v = 1U * s1 * s2;

这不是皈依 1U uint32_t的 S1 S2 unsigned int类型,取决于什么是适合你的特定平台。

This either converts 1U to uint32_t, or s1 and s2 to unsigned int, depending on what's appropriate for your particular platform.

@Deduplicator评论说,一些编译器,其中 uint32_t的 unsigned int类型窄,可能会警告有关隐式转换在分配,并指出,这种警告是通过使转换明确可能燮pressable:

@Deduplicator comments that some compilers, where uint32_t is narrower than unsigned int, may warn about the implicit conversion in the assignment, and notes that such warnings are likely suppressable by making the conversion explicit:

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

看起来少了几分优雅,在我看来,虽然。

It looks a bit less elegant, in my opinion, though.

这篇关于在64位导致未定义行为的32位无符号乘法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆