移位32位变量32位有什么不好?

时间:2010-04-15 20:30:58

标签: c bit-manipulation 32bit-64bit

我最近选择了Bruce Schneier的应用密码学副本,这是一本很好的阅读。我现在明白本书中概述的几种算法是如何工作的,我想在C中开始实现其中的一些算法。

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

这是我陷入困境的地方。我对C很相当,但对于按位运算符等我并不是最强的。

在对IRC提供一些帮助后,我设法提出了这两个宏:

#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位。

我的问题是这些:

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

正如我所说的,我对C非常熟悉,但是按位运算符等仍让我头疼。

修改

我发现我的组合宏实际上并没有组合两个32位变量,而只是简单地将0与0进行对比,并得到一个结果。
所以,除了我之前的问题,我仍然没有一种方法将两个32位变量组合起来得到一个64位变量;关于如何做的建议将不胜感激。

5 个答案:

答案 0 :(得分:22)

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

  

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

     

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

C11又称ISO / IEC 9899:2011也是如此。

首先应将b强制转换为目标整数类型。另一点是你应该在宏参数周​​围加上括号,以避免运算符优先级出现意外。此外,逗号运算符在这里非常有用,允许您避免使用大括号,以便宏可以用作普通命令,以分号结束。

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

可能需要额外的强制转换来“拆分”以消除过度偏执编译器精确丢失的警告。

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

请不要考虑将自编加密用于生产代码。

答案 1 :(得分:12)

在C和C ++中未定义32位或32位以上的值。未定义的原因之一是在某些硬件平台上,32位移位指令仅考虑提供的移位计数的5个最低位。这意味着无论你传递的移位数是多少,它都会被模数解释为32.试图在这样的平台上移动32实际上会移0,即根本不移位。

语言作者不希望为这种平台编写的编译器负担,其任务是在进行转换之前分析班次计数。相反,语言规范说行为是未定义的。这意味着如果您希望从32位移位获得0(或更多)的0值,则由您来识别情况并相应地处理它。

答案 2 :(得分:3)

  

将32位变量32位移位有什么不好?

最好将0分配给n位整数,而不是将其移位n位。

示例:

 0 0 1 0 1 ----- 5 bit Integer  
 0 1 0 1 0 ----- 1st shift  
 1 0 1 0 0 ----- 2nd shift  
 0 1 0 0 0 ----- 3rd shift  
 1 0 0 0 0 ----- 4th shift  
 0 0 0 0 0 ----- 5th shift (all the bits are shifted!)  

  

我仍然没有一种方法将两个32位变量组合起来得到一个64位的

考虑: a为64位,bc为32位

a = b;
a = a << 32; //Note: a is 64 bit
a = a | c;

答案 3 :(得分:0)

除非这是“重新发明轮子以了解其工作原理”项目,否则不要实现自己的加密功能。

自从。

使用可用的算法(以及选择正确的算法)是很困难的,不要通过投入生产一些自制的密码API来自己动手。机会为your encryption won't encrypt

答案 4 :(得分:0)

  

将32位变量32位移位有什么不好?

除了已经说过的内容之外, 32nd 位是符号位,你可以通过符号扩展来保留唱,从而丢失有效位。

相关问题