【发布时间】:2014-01-26 02:05:55
【问题描述】:
我有一个接收 3 个参数的方法:int x、int n 和 int m。它返回一个交换了 x 的第 n 个和第 m 个字节的 int
x 只是一个普通的整数,设置为任何值。 n 和 m 是 0 到 3 之间的整数。
例如,设 x 的十六进制表示为 0x12345678,n 为 0,m 为 2。 最后一个和倒数第三个字节应该被交换(n = 78,m = 34)。
我已经弄清楚如何从 x 中提取第 n 个和第 m 个字节,但我不知道如何将所有 4 个字节重新组合成该方法应该返回的整数。
这是我当前的代码: `
int byteSwap(int x, int n, int m)
{
// Initialize variables which will hold nth and mth byte
int xn = x;
int xm = x;
// If n is in bytes, n << 3 will be the number of bits in that byte
// For example, if n is 2 (as in 2 bytes), n << 3 will be 16 (as in 16 bits)
xn = x >> (n << 3);
// Mask off everything except the part we want
xn = xn & 0xFF;
// Do the same for m
xm = x >> (m << 3);
xm = xm & 0xFF;
}
`
还有一些额外的限制 - 只允许以下:
~ & ^ | ! + << >>
(也就是说没有- * /、循环、ifs等。但是,可以初始化额外的变量,添加仍然可以。)
我的代码可以提取第 n 个和第 m 个字节,但我不知道如何在不使用 ifs 的情况下重组所有内容。
【问题讨论】:
-
一些建议 - 当位摆弄时,使用无符号整数类型是个好主意。 C 不保证有符号整数将使用任何特定的表示 - 如果没有明确定义数字如何转换为/从位,位摆弄很容易出错。在实践中,对于任何不完全陌生的平台,表示将是二进制补码,但编译器出于优化原因越来越多地利用不确定性。因此,即使您知道您的平台使用二进制补码,您也可能会得到与之不一致的行为,这取决于编译器的突发奇想。
-
是否允许强制转换和指针? (例如 unsigned char* bytes = (unsigned char*)&x;)
-
不,不允许强制转换和指针。这是一个家庭作业问题,并指定有符号整数的表示形式为二进制补码。
-
@thepwner224 - 我的评论的重点是表示是否是二进制补码并不重要。未定义的行为是未定义的行为——编译器可以为所欲为。当然,如果你被特别告知你可能会使用这些知识,但对我来说,这只是意味着你有一个糟糕的老师——在一些地方写
unsigned的成本远远低于调查怪异的成本在调试版本或其他任何东西中消失的错误。此外,无符号位摆弄意味着您不必对符号位进行特殊处理。 -
@thepwner224 - 用有符号整数摆弄你的位的唯一原因是如果你使用 Java,它没有无符号整数,但至少保证 2s 补码表示没有未定义的行为。
标签: c byte swap byte-shifting