将 32 位变量移位 32 位有什么不好? [英] What's bad about shifting a 32-bit variable 32 bits?

查看:25
本文介绍了将 32 位变量移位 32 位有什么不好?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近拿起了 Bruce Schneier 的 Applied Cryptography 的副本,读得很好.我现在了解书中概述的几种算法是如何工作的,我想开始用 C 实现其中的一些算法.

I recently picked up a copy of Applied Cryptography by Bruce Schneier and it's been a good read. I now understand how several algorithms outlined in the book work, and I'd like to start implementing a few of them in C.

许多算法的共同点是将 x 位密钥划分为几个较小的 y 位密钥.例如,Blowfish 的密钥 X 是 64 位的,但是您需要将其分成两个 32 位的一半;Xl 和 Xr.

One thing that many of the algorithms have in common is dividing an x-bit key, into several smaller y-bit keys. For example, Blowfish's key, X, is 64-bits, but you are required to break it up into two 32-bit halves; Xl and Xr.

这就是我被卡住的地方.我在 C 方面相当不错,但在按位运算符等方面我并不是最强大的.

This is where I'm getting stuck. I'm fairly decent with C, but I'm not the strongest when it comes to bitwise operators and the like.

在 IRC 上的一些帮助之后,我设法想出了这两个宏:

After some help on IRC, I managed to come up with these two macros:

#define splitup(a, b, c) {b = a >> 32; c = a & 0xffffffff; }
#define combine(a, b, c) {a = (c << 32) | a;}

其中 a 是 64 位,b 和 c 是 32 位.但是,编译器警告我我将 32 位变量移动了 32 位.

Where a is 64 bits and b and c are 32 bits. However, the compiler warns me about the fact that I'm shifting a 32 bit variable by 32 bits.

我的问题是:

  • 将 32 位变量移位 32 位有什么不好?我猜它是未定义的,但这些宏似乎确实有效.
  • 另外,你会建议我换一种方式吗?

正如我所说,我对 C 相当熟悉,但按位运算符等仍然让我头疼.

As I said, I'm fairly familiar with C, but bitwise operators and the like still give me a headache.

编辑

我发现我的组合宏实际上并不是组合两个 32 位变量,而是简单地将 0 与 a 进行 OR 运算,然后得到 a.
所以,在我之前的问题之上,我仍然没有将两个 32 位变量组合起来得到一个 64 位变量的方法;不胜感激.

I figured out that my combine macro wasn't actually combining two 32-bit variables, but simply ORing 0 by a, and getting a as a result.
So, on top of my previous questions, I still don't have a method of combining the two 32-bit variables to get a 64-bit one; a suggestion on how to do it would be appreciated.

推荐答案

是的,这是未定义的行为.

Yes, it is undefined behaviour.

ISO/IEC 9899:1999 6.5.7 按位移位运算符 ¶3

ISO/IEC 9899:1999 6.5.7 Bitwise shift operators ¶3

对每个操作数执行整数提升.结果的类型是提升的左操作数的类型.如果右操作数的值为负或大于或等于提升的左操作数的宽度,则行为未定义.

The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

C11 aka ISO/IEC 9899:2011 也有同样的说法.

您应该首先将 b 转换为目标整数类型.另一点是您应该在宏参数周​​围放置括号以避免运算符优先级的意外.此外,逗号运算符在这里非常有用,可以让您避免使用大括号,这样宏就可以用作普通命令,用分号结束.

You should first cast b to the target integer type. Another point is that you should put parentheses around the macro parameters to avoid surprises by operator precedences. Additionally, the comma operator is very useful here, allowing you to avoid the braces, so that the macro can be used as a normal command, closed with a semicolon.

#define splitup(a,b,c) ( (b) = (a) >> 32, (c) = (a) & 0xffffffff )
#define combine(a,b,c) ( (a) = ((unsigned long long)(b) << 32) | (c) )

可能需要额外的强制转换,以消除过度偏执的编译器有关精度损失的警告.

Additional casts may be necessary for `splitup to silence warnings about precision loss by over-paranoid compilers.

#define splitup(a,b,c) ( (b) = (unsigned long)((a) >> 32), (c) = (unsigned long)((a) & 0xffffffff) )

并且请不要考虑将您自己编写的加密用于生产代码.

And please don't even think about using your self-written encryption for production code.

这篇关于将 32 位变量移位 32 位有什么不好?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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