简体   繁体   English

十六进制数字的C位运算

[英]C bit-wise operations with hex numbers

Is there a way to access certain parts of a hexadecimal number in C? 有没有办法访问C中十六进制数字的某些部分?

I want to write a function that takes in a hexadecimal number and negates it, but leaves the least significant byte unchanged. 我想编写一个接受十六进制数字并将其取反的函数,但保留最低有效字节不变。 Example: 0x87654321 should become 0x789ABC21. 示例:0x87654321应该变成0x789ABC21。

I've tried to somehow save the LSB and then apply it to the negated x, but my problem is that my mask gets applied to all bytes. 我试图以某种方式保存LSB,然后将其应用于取反的x,但是我的问题是我的掩码被应用于所有字节。 I could hard code it for a specific value, but obviously that's not what I want. 我可以将其硬编码为特定值,但是显然那不是我想要的。

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
}

I'd appreciate if you don't post code for the solution, but rather just answer whether there is a way to apply bit operations to specific sections of a hexadecimal number, or how I could possibly solve this. 如果您不发布解决方案的代码,而只是回答是否有一种方法可以将位运算应用于十六进制数的特定部分,或者我如何解决此问题,我将不胜感激。

In general you can operate on specific bits of a value by using a mask . 通常,您可以使用掩码对值的特定位进行操作。

A mask is bit-pattern with 1s where you want to operate and 0s where you don't. 掩码是位模式,您要操作的位为1,不需要时为0。

It seems like you need 3 operations: extract lowest byte, negate, restore lowest byte. 似乎您需要3个操作:提取最低字节,取反,恢复最低字节。 You can figure out negation, so I'll just talk about extracting a bit-field and restoring an extracted bit-field. 您可以找出否定的含义,因此我将只讨论提取位域并恢复提取的位域。

To extract specified bits, use a mask with 1s for the desired bits and use the bitwise and operator & . 以提取特定的比特,使用具有1秒的掩模用于所需比特和使用按位运算符& The and operator sets 0s for all 0s of the mask, and where the mask is 1, it copies the bits from the other argument. and运算符将掩码的所有0都设置为0,并且掩码为1时,它将复制另一个自变量中的位。 If you need to examine this value elsewhere in your program, it may also be convenient to right-shift >> the value down to the lowest position (so it's easier to lookup in tables). 如果您需要在程序的其他位置检查此值,将值右移>>到最低位置也很方便(因此在表中查找更容易)。

To restore saved bits, shift back up if you shifted it down earlier. 要恢复保存的位,如果您早先将其下移,则将其上移。 Then clear those bits from the value, and use inclusive-or | 然后从值中清除这些位,并使用包含-或 | as a bitwise sum of all one bits. 作为所有一位的按位求和。 To clear the bits from the value, use the inverse of the mask from the first operation. 要从值中清除位,请使用第一个操作中的掩码的倒数。 Ie. IE浏览器。 y = x & 0xf saves a nibble, x & ~0xf clears that nibble, (x & ~0xf) | y y = x & 0xf保存一个半字节, x & ~0xf清除该半字节, (x & ~0xf) | y (x & ~0xf) | y recombines to the same original x. (x & ~0xf) | y重组为相同的原始x。

Edit: If the piece you're extracting is not in the lowest position, say the second byte (LSB) from a 32 bit unsigned integer, then it may be useful to shift the extracted value to the zero position to work with it. 编辑:如果要提取的片段不在最低位置,例如说32位无符号整数的第二个字节(LSB),则将提取的值移到零位置以使用它可能会很有用。

x = 0x12345678;
y = x & 0xFF00;  // == 0x5600
y >>= 8;         // == 0x56

But if you do this then you have to shift it back to the correct position (of course) before updating the larger value with a new value for the bitfield. 但是,如果这样做,则必须先将其移回到正确的位置(当然),然后再用位域的新值更新较大的值。

x = (x & ~0xFF00) | (y << 8);

If I correctly understood the question, seems like it would be something like this (untested). 如果我正确理解了这个问题,似乎就是这样(未经测试)。

void b(int x) {
  return (~x & ~0xFF) | (x & 0xFF);
}

I've found a way to manipulate a chosen byte. 我找到了一种操纵选定字节的方法。 (!!! This would be homework 2.60 of CS:APP !!!) (!!!这将是CS:APP的作业2.60 !!!)

If 0x12345678 is a given hexadecimal value of type, say int, then doing this will allow me to change the ith byte: 如果0x12345678是给定类型的十六进制值,例如int,那么这样做将允许我更改第i个字节:

int x = 0x12345678;
unsigned char* xptr = (unsigned char*) &x;
xptr[i] = 0; // say i=2, then this would yield: 0x120045678

Now, if I want to add a value in the position of byte i, say 0xAB, I'd do what luser droog already mentioned: 现在,如果我想在字节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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM