C 更改数据包流中的特定字节

C 更改数据包流中的特定字节,c,C,我使用C来实现一个通过无线发送的数据包流,我遇到了以下问题。我有一个2字节长的无符号整数,二进制格式如下: XXXX YYYY XXXX,其中X&Y是位 查看上面的格式,我只需要更改YYYY位,并在数据包结构中保留其他位 我尝试过移位和掩蔽,但似乎没有任何效果 我不只是寻找一个解决方案,以便我可以复制/粘贴。我想学习如何让它工作的方法,最后决定张贴在这里 在正确的方向上提供任何帮助或指导都是非常好的 谢谢 value=(value&0xF0FF)|(newYvalue=(value&0xF0FF

我使用C来实现一个通过无线发送的数据包流,我遇到了以下问题。我有一个2字节长的无符号整数,二进制格式如下: XXXX YYYY XXXX,其中X&Y是位

查看上面的格式,我只需要更改YYYY位,并在数据包结构中保留其他位

我尝试过移位和掩蔽,但似乎没有任何效果

我不只是寻找一个解决方案,以便我可以复制/粘贴。我想学习如何让它工作的方法,最后决定张贴在这里

在正确的方向上提供任何帮助或指导都是非常好的


谢谢

value=(value&0xF0FF)|(newY
value=(value&0xF0FF)|(newY假设您想用ZZZZ替换YYYY位

首先,您需要清除原始值中的YYYY位。这可以通过以下方法完成:

oldvalue & 0xF0FF
这将为您提供
XXXX 0000 XXXX XXXX

接下来,您需要将新的ZZZZ位移到左侧,使用:

z << 8

这将为您提供
XXXX ZZZZ XXXX XXXX

假设您想用ZZZZ替换YYYY位

首先,您需要清除原始值中的YYYY位。这可以通过以下方法完成:

oldvalue & 0xF0FF
这将为您提供
XXXX 0000 XXXX XXXX

接下来,您需要将新的ZZZZ位移到左侧,使用:

z << 8

这就给了你一个问题的描述,这个问题可能与一些代码有关,但我认为你可能遇到了一个endian问题。这可以解释为什么你的移位和掩蔽没有像你想象的那样做,因为你实际上在处理错误的字节

hton和ntoh系列函数在主机端和网络端(big-endian)之间切换。有关详细信息,请查阅hton、ntoh、htonl和ntohl。如果主机是big-endian,则这些函数实际上不会执行任何操作,但许多(如x86)计算机是little-endian。在little-endian计算机上是htons(0x1234)将导致0x3412,因为它交换字节

因为我不知道你的程序流是什么样子,所以这里是我最好的一个清晰的例子

uint16_t set_those_bits(uint16_t x) {
    uint16_t mask = htons(0x0F00);
    return x | mask;
}
此函数不会改变相对于返回值传入的数据的endian值,但它会假定该值为network endian,因此会将掩码的endian值从host endian更改为network,然后在结果中设置这些位

uint16_t clear_those_bits(uint16_t x) {
    uint16_t mask = htons(0xF0FF);
    return x & mask;
}

uint16_t toggle_those_bits(uint16_t x) {
    uint16_t mask = htons(0x0f00);
    return x ^ mask;
}

您对问题的描述可能与一些代码有关,但我认为您可能遇到了endian问题。这可以解释为什么您的移位和掩蔽没有像您认为的那样做,因为您实际上在处理错误的字节

hton和ntoh系列函数在主机端和网络端(big-endian)之间切换。有关详细信息,请查阅hton、ntoh、htonl和ntohl。如果主机是big-endian,则这些函数实际上不会执行任何操作,但许多(如x86)计算机是little-endian。在little-endian计算机上是htons(0x1234)将导致0x3412,因为它交换字节

因为我不知道你的程序流是什么样子,所以这里是我最好的一个清晰的例子

uint16_t set_those_bits(uint16_t x) {
    uint16_t mask = htons(0x0F00);
    return x | mask;
}
此函数不会改变相对于返回值传入的数据的endian值,但它会假定该值为network endian,因此会将掩码的endian值从host endian更改为network,然后在结果中设置这些位

uint16_t clear_those_bits(uint16_t x) {
    uint16_t mask = htons(0xF0FF);
    return x & mask;
}

uint16_t toggle_those_bits(uint16_t x) {
    uint16_t mask = htons(0x0f00);
    return x ^ mask;
}

太好了!谢谢。在发布这个问题后,我再次尝试,并提出了相同的逻辑,但您的代码更简单,更切题(我有4行代码来完成一行中的工作)没问题,skybox-很高兴能为您提供帮助!太好了!谢谢您。发布此问题后,我再次尝试,并提出了相同的逻辑,但您的代码更简单,更切中要害(我有4行代码来完成一行中的工作)没问题,skybox-很高兴能提供帮助!谢谢你的解释!感谢你的解释!感谢你的解释!感谢你的解释!感谢你的解释!感谢你的解释!关于little/big endian的经验教训。对于数字世界来说是新的。我将更多地了解你的代码并尝试理解它。谢谢!关于little/big endian的经验教训。对于数字世界来说是新的。我将更加了解输入你的代码,并尝试找出它。