C 十六进制数的按位运算
C bit-wise operations with hex numbers
有没有办法在 C 中访问十六进制数的某些部分?
我想编写一个函数,它接受一个十六进制数并将其取反,但保留最低有效字节不变。示例:0x87654321 应变为 0x789ABC21。
我试图以某种方式保存 LSB,然后将其应用于取反的 x,但我的问题是我的掩码应用于所有字节。我可以将其硬编码为特定值,但显然这不是我想要的。
void b(int x) {
int temp = x & 0xFF; // temp is all 0 with the LSB being the same as x's
x = ~x; // this negates x
// one of a couple of attempts I tried thus far:
// x = (x & 0x00) | temp;
// idea: change x's LSB to 00 and OR it with temp,
// changing x's LSB to temp's LSB
}
如果您不post解决方案的代码,我将不胜感激,而只是回答是否有一种方法可以将位操作应用于十六进制数的特定部分,或者我如何可能解决这个问题。
通常,您可以使用 掩码.
对值的特定位进行操作
掩码是位模式,在您要操作的地方为 1,在您不想操作的地方为 0。
看来您需要 3 个操作:提取最低字节、取反、恢复最低字节。否定你可以算出来,所以我只说提取一个位域和恢复一个提取的位域。
要提取指定位,请对所需位使用带 1 的掩码并使用按位 和 运算符 &
。 and 运算符将掩码的所有 0 设置为 0,并且在掩码为 1 的情况下,它从另一个参数复制位。如果您需要在程序的其他地方检查此值,也可以方便地将 >>
值右移到最低位置(这样更容易在表中查找)。
要恢复保存的位,如果您之前将其向下移动,请将其向上移动。然后从值中清除这些位,并使用 inclusive-or |
作为所有一位的按位和。要清除值中的位,请使用第一个操作中掩码的逆运算。 IE。 y = x & 0xf
保存一个半字节,x & ~0xf
清除该半字节,(x & ~0xf) | y
重新组合为相同的原始 x。
编辑:
如果您要提取的部分不在最低位置,比如 32 位无符号整数的第二个字节 (LSB),那么将提取的值移动到零位置以使用它可能很有用。
x = 0x12345678;
y = x & 0xFF00; // == 0x5600
y >>= 8; // == 0x56
但是如果你这样做,那么你必须将它移回正确的位置(当然),然后再用位域的新值更新较大的值。
x = (x & ~0xFF00) | (y << 8);
如果我正确理解了这个问题,那么它应该是这样的(未经测试)。
void b(int x) {
return (~x & ~0xFF) | (x & 0xFF);
}
我找到了一种操作所选字节的方法。 (!!! 这将是 CS:APP 的作业 2.60 !!!)
如果 0x12345678 是给定的十六进制值类型,比如 int,那么这样做将允许我更改第 i 个字节:
int x = 0x12345678;
unsigned char* xptr = (unsigned char*) &x;
xptr[i] = 0; // say i=2, then this would yield: 0x120045678
现在,如果我想在字节 i 的位置添加一个值,比如说 0xAB,我会做 luser droog 已经提到的:
int temp = 0xAB;
temp = temp << i*8; // say i=2, then this would yield: 0x00AB0000
x = x | temp; // this yields the desired result 0x12AB3456
有没有办法在 C 中访问十六进制数的某些部分?
我想编写一个函数,它接受一个十六进制数并将其取反,但保留最低有效字节不变。示例:0x87654321 应变为 0x789ABC21。
我试图以某种方式保存 LSB,然后将其应用于取反的 x,但我的问题是我的掩码应用于所有字节。我可以将其硬编码为特定值,但显然这不是我想要的。
void b(int x) {
int temp = x & 0xFF; // temp is all 0 with the LSB being the same as x's
x = ~x; // this negates x
// one of a couple of attempts I tried thus far:
// x = (x & 0x00) | temp;
// idea: change x's LSB to 00 and OR it with temp,
// changing x's LSB to temp's LSB
}
如果您不post解决方案的代码,我将不胜感激,而只是回答是否有一种方法可以将位操作应用于十六进制数的特定部分,或者我如何可能解决这个问题。
通常,您可以使用 掩码.
对值的特定位进行操作掩码是位模式,在您要操作的地方为 1,在您不想操作的地方为 0。
看来您需要 3 个操作:提取最低字节、取反、恢复最低字节。否定你可以算出来,所以我只说提取一个位域和恢复一个提取的位域。
要提取指定位,请对所需位使用带 1 的掩码并使用按位 和 运算符 &
。 and 运算符将掩码的所有 0 设置为 0,并且在掩码为 1 的情况下,它从另一个参数复制位。如果您需要在程序的其他地方检查此值,也可以方便地将 >>
值右移到最低位置(这样更容易在表中查找)。
要恢复保存的位,如果您之前将其向下移动,请将其向上移动。然后从值中清除这些位,并使用 inclusive-or |
作为所有一位的按位和。要清除值中的位,请使用第一个操作中掩码的逆运算。 IE。 y = x & 0xf
保存一个半字节,x & ~0xf
清除该半字节,(x & ~0xf) | y
重新组合为相同的原始 x。
编辑: 如果您要提取的部分不在最低位置,比如 32 位无符号整数的第二个字节 (LSB),那么将提取的值移动到零位置以使用它可能很有用。
x = 0x12345678;
y = x & 0xFF00; // == 0x5600
y >>= 8; // == 0x56
但是如果你这样做,那么你必须将它移回正确的位置(当然),然后再用位域的新值更新较大的值。
x = (x & ~0xFF00) | (y << 8);
如果我正确理解了这个问题,那么它应该是这样的(未经测试)。
void b(int x) {
return (~x & ~0xFF) | (x & 0xFF);
}
我找到了一种操作所选字节的方法。 (!!! 这将是 CS:APP 的作业 2.60 !!!)
如果 0x12345678 是给定的十六进制值类型,比如 int,那么这样做将允许我更改第 i 个字节:
int x = 0x12345678;
unsigned char* xptr = (unsigned char*) &x;
xptr[i] = 0; // say i=2, then this would yield: 0x120045678
现在,如果我想在字节 i 的位置添加一个值,比如说 0xAB,我会做 luser droog 已经提到的:
int temp = 0xAB;
temp = temp << i*8; // say i=2, then this would yield: 0x00AB0000
x = x | temp; // this yields the desired result 0x12AB3456