在C语言中,给定一系列字节,如何复制一个字节,然后复制那个字节?
我的一个家庭作业问题是获取一个给定的字节序列,用无符号int表示,然后复制某个字节,从而将该序列扩展一个字节。例如,如果我要对十六进制表示为0xAABBCC的无符号整数执行此函数,同时指定扩展第二个字节,则在该函数前后输出十六进制值如下所示:在C语言中,给定一系列字节,如何复制一个字节,然后复制那个字节?,c,bit-manipulation,bitwise-operators,C,Bit Manipulation,Bitwise Operators,我的一个家庭作业问题是获取一个给定的字节序列,用无符号int表示,然后复制某个字节,从而将该序列扩展一个字节。例如,如果我要对十六进制表示为0xAABBCC的无符号整数执行此函数,同时指定扩展第二个字节,则在该函数前后输出十六进制值如下所示: 0xAABBCC -> 0xAABBBBCC 我已经取得了一些进展,因为我觉得我确实很了解位运算符,但我不知道如何使用位运算符来执行像这样更复杂的任务。鉴于这是一个家庭作业问题,我很乐意回答有关位运算符的文章的链接,但请记住,我确实掌握了基本知识,
0xAABBCC -> 0xAABBBBCC
我已经取得了一些进展,因为我觉得我确实很了解位运算符,但我不知道如何使用位运算符来执行像这样更复杂的任务。鉴于这是一个家庭作业问题,我很乐意回答有关位运算符的文章的链接,但请记住,我确实掌握了基本知识,我更愿意看到一系列位运算符的实际示例
这是到目前为止我掌握的代码。它似乎接近工作状态,但我无法掌握如何将重复的字节插入到字节序列的中间
unsigned long long extend_byte(unsigned x, unsigned i) //x = 0xAABBCC, i = 1
{
printf("%x\n", x); //0xaabbcc
int shiftVal = i << 3;
unsigned mask = 0xFF << shiftVal;
printf("%x\n", mask); //0x00ff
unsigned byteToCopy = x | ~mask;
printf("%x\n", byteToCopy); //0xffffbbff
x &= byteToCopy;
printf("%x\n", x); //aabbcc
return x;
}
无符号长扩展_字节(无符号x,无符号i)//x=0xAABBCC,i=1
{
printf(“%x\n”,x);//0xaabbcc
int shiftVal=i问题在于您的掩码屏蔽了单个字节,您需要屏蔽要复制的字节右侧的所有数字,并使用不同的掩码屏蔽该字节左侧的所有数字。检查如下:
uint64_t extend_byte(uint64_t x, uint64_t i) // 0x0000000011223344 and 3
{
uint64_t allOnes = ~0x00ULL; // 0xFFFFFFFFFFFFFFFF
uint64_t shiftVal = i << 3; // i << 3 == i * 8 == 24 bits = 3 bytes
uint64_t leftMask = allOnes << shiftVal; // 0xFFFFFFFFFF000000
uint64_t leftPart = (x << 8) & leftMask; // 0x0000001122000000
uint64_t rightMask = ~leftMask; // 0x0000000000FFFFFF
uint64_t rightPart = x & ~rightMask; // 0x0000000000223344
return leftPart | rightPart; // 0x0000001122223344
}
uint64\u t扩展字节(uint64\u t x,uint64\u t i)//0x0000000011223344和3
{
uint64\u t allOnes=~0x00ULL;//0xFFFFFFFFFFFFFFFF
uint64\u t shiftVal=i这是我提出的代码。注释中解释了大多数想法
#include by产生不正确的结果。当替换我的byte_extend()
版本时,它会产生以下输出:
0x00AABBCC移位0=0xAABBFFCC
0x00AABBCC移位1=0xAABBFF00
0x00AABBCC移位2=0xAABB0000
0x00AABBCC移位3=0xAA000000
0x88776655FFEDDCC移位0=0xFF7777FFFFDDCC
0x88776655FFEDDCC移位1=0xFF7777FFFFDD00
0x88776655FFEEDCC移位2=0xFF7777FFFF0000
0x88776655FFEEDCC移位3=0xFF7777FFFF000000
0x88776655FFEEDCC移位4=0xFF7777FF00000000
0x88776655FFEEDCC移位5=0xFF7777000000000
0x88776655FFEEDCC移位6=0xFF7700000000000
0x88776655FFEEDCC移位7=0xFF00000000000000
如何计算字节数?最低有效字节是否算作字节1?如果要复制字节1,结果是否为0xAABBCCCC?如果要复制字节3,结果是否为0xAAAABBCC?如果要复制字节4,则不会有任何更改?@Jonathan Leffler,它们从右侧的0开始索引。在我的示例中,字节0对应于CC,字节1对应于BB,字节2对应于AA。假定不会给出索引外字节。您的示例(第二个字节将0x00AABBCC复制到0xAABBCC)与注释中的规范不匹配(LSB是字节0)。您正在使用示例值复制字节1,尽管声明您正在复制字节2。此外,您的函数签名有点奇怪。您接收一个无符号
,然后处理该无符号
值,然后返回它,声称返回时它将是一个无符号长
。它将是一个4-byte整数零填充为返回的8个字节;x
的前导字节将不会为任何有效移位保留。@Jonathan Leffler是的,我知道这有多混乱,但我指的是第二个字节,如字节[1]中的字节索引从0开始。函数签名就是这样给我的,但是你是说将x转换成有符号的long会保留前导字节吗?因为据我所知,这就是会发生的情况。uint8
非常混乱。为什么不使用标准的uint64\t
?你甚至不需要8字节数为4就可以了。请注意,在大多数系统上,~0x00
将是0xFFFFFFFF
(因为0x00是一个int
,它占用了4个字节,因此~0x00
)您需要~0x00ULL
才能获得0xffffffffffff
leftPart=(x谢谢,这是一个很有帮助的解决方案。看看每一行,我都明白它是如何工作的,但我不可能自己做到这一点。你能推荐一些资源来练习更高级的比特技术吗?比如这一种,这样可以在本学期的晚些时候练习,而不会措手不及。事实上,有有一件事我不明白。在第6行中,为什么你要特别按8换班?我如何决定在这里换班?