Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C语言中,给定一系列字节,如何复制一个字节,然后复制那个字节?_C_Bit Manipulation_Bitwise Operators - Fatal编程技术网

在C语言中,给定一系列字节,如何复制一个字节,然后复制那个字节?

在C语言中,给定一系列字节,如何复制一个字节,然后复制那个字节?,c,bit-manipulation,bitwise-operators,C,Bit Manipulation,Bitwise Operators,我的一个家庭作业问题是获取一个给定的字节序列,用无符号int表示,然后复制某个字节,从而将该序列扩展一个字节。例如,如果我要对十六进制表示为0xAABBCC的无符号整数执行此函数,同时指定扩展第二个字节,则在该函数前后输出十六进制值如下所示: 0xAABBCC -> 0xAABBBBCC 我已经取得了一些进展,因为我觉得我确实很了解位运算符,但我不知道如何使用位运算符来执行像这样更复杂的任务。鉴于这是一个家庭作业问题,我很乐意回答有关位运算符的文章的链接,但请记住,我确实掌握了基本知识,

我的一个家庭作业问题是获取一个给定的字节序列,用无符号int表示,然后复制某个字节,从而将该序列扩展一个字节。例如,如果我要对十六进制表示为0xAABBCC的无符号整数执行此函数,同时指定扩展第二个字节,则在该函数前后输出十六进制值如下所示:

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换班?我如何决定在这里换班?