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

标签 c bit-manipulation 32bit-64bit

我最近买了一本 Bruce Schneier 的 Applied Cryptography,读起来很不错。我现在明白了书中概述的几种算法是如何工作的,我想开始用 C 语言实现其中的一些。

许多算法的一个共同点是将一个 x 位 key 分成几个较小的 y 位 key 。例如,Blowfish 的 key 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 与 a 进行或运算,并得到一个结果。
因此,除了我之前的问题之外,我仍然没有一种方法可以将两个 32 位变量组合起来得到一个 64 位变量;我们将不胜感激。

最佳答案

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

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 转换为目标整数类型。另一点是您应该在宏参数周​​围加上括号,以避免运算符优先级出现意外。此外,逗号运算符在这里非常有用,它可以让您避免使用大括号,这样宏就可以用作普通命令,以分号结束。

#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) )

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

关于c - 将 32 位变量移动 32 位有什么不好?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58011502/

相关文章:

c - 在DOS下处理以太网中断

c++ - 多类作业

c - 将零输入输出作为共享内存变量的值

Java:按位AND创建无符号字节

hash - 32 位数字的逆乘法

windows - java 在我的 64 位机器的任务管理器中显示为 32 位

python - 在 64 位 linux 机器上运行 32 位 Python 脚本以使用 32 位客户端连接到 oracle DB

python - 如何在 64 位 CentOS 6 上编译运行 32 位 Python?

c - 底层套接字编程

c - 结构类型数组