【问题标题】:How do I properly byte shift a chunk of data?如何正确地对一大块数据进行字节移位?
【发布时间】:2017-11-22 19:22:25
【问题描述】:

我有一个mmap

void *mymap;
mymap = mmap(0, attr.st_size, PROT_READ|PROT_WRITE, MAPFILE|MAP_SHARED, fd, 0);

我打开了一个 HEX 内容为 0x25362364 的文件

00100101001101100010001101100100

二进制。现在我想执行位移:

char *str = (char *)mymap;
for(int i=0;i<attr.st_size;i++) {
    str[i] = str[i] >> 4;
}

我的新文件包含新的二进制数

00000010000000110000001000000110

但希望的结果是将所有内容向右移动 4 位:

00000010010100110110001000110110

我怎样才能做到这一点? 额外问题:如果二进制数 MSB 为 1,我如何在右移时让左侧填充 0?

【问题讨论】:

  • 我们可以从您的方法不起作用的原因开始。一个字符是 8 位宽。当您移动每个字符的位时,您会丢弃从每个单独聊天中移出的位;它不会被推送到数组中的下一个字符。现在对于解决方案,这可能取决于这个问题:您正在使用的字节数是恒定的,还是会发生变化?
  • 哦,如果你想确保在 MSB 为 1 时移入 0,我相信你应该使用无符号类型。
  • 字节数将会改变。感谢您的回复
  • 使用 Wea​​ther Vane 的解决方案(并将其标记为已接受)。这是为您的用例执行此操作的最佳方式。
  • 据我所知,它最多只能工作 8 位。如果我想移动几百位怎么办?

标签: c memory-mapped-files memory-mapping


【解决方案1】:

数组中的每个字节应右移 4 位,并与前一个(无符号)字节左移 4 位进行或运算。例如

unsigned char *str = (unsigned char *)mymap;
unsigned char prev = 0, next;
for(int i = 0; i < attr.st_size; i++) {
    next  = str[i];
    str[i] = (str[i] >> 4) | (prev << 4);
    prev = next;    
}

如果您想要右移 5 位,您可以右移 5 位,左移 3 位,总和 = 8(假设 CHAR_BIT 为 8)。

【讨论】:

  • 感谢您的帮助,这行得通。但是如果我想移动超过 8 位,甚至高达几百位(如果它是一个更大的文件),我该怎么办
  • 然后使用unsigned intunsigned long long的数组并相应地修改算法。不过,您可能需要注意字节顺序。这种方法不适用于 100 位,但这应该是一个不同的问题。嗯,你有 128 位数据类型可用吗?
  • 我建议移动大量位,构建另一个数组,具有适当的索引偏移和移位。
  • 如果你想移动 100 位,你可以移动 12 字节(使用 memmove 或类似方法),然后移动 4 位。
  • @immibis 所说的。您基本上会进行移动整个字节的“粗略移位”,然后以 WeatherVane 已经提供的“精细移位”结束。
猜你喜欢
  • 2013-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-08
  • 1970-01-01
  • 1970-01-01
  • 2016-06-02
  • 2021-10-25
相关资源
最近更新 更多