【问题标题】:C Bitwise OR changing value unexpectedlyC按位或意外更改值
【发布时间】:2017-04-09 05:15:26
【问题描述】:

我目前正在编写一个涉及二进制内存的程序,我需要一个无符号长整型中的某个位序列。

现在,我正在循环这个代码块 4 次以尝试创建一个 32 位序列。

unsigned long long int currentEntry = 0;
for (int j = 0; j < 4; ++j){
    currentEntry = (currentEntry << 8);
    currentEntry = (currentEntry | (unsigned long long int)entryBuffer[i][j]);
}

entrybuffer[i][j] 是一个 char,它包含一个字节值,我将它转换为一个 unsigned long long int,据我所知,它似乎正在工作,直到我遇到一个奇怪的错误。 例如,这里是二进制形式的 currentEntry 变量:

//goal bit sequence: 00001000000001001010000011000000

currentEntry = (currentEntry << 8); 
//00000000
currentEntry = (currentEntry | (unsigned long long int)entryBuffer[i][j]); //entrybuffer[i][j] = 00001000
//00001000
currentEntry = (currentEntry << 8); 
//0000100000000000
currentEntry = (currentEntry | (unsigned long long int)entryBuffer[i][j]); //entrybuffer[i][j] = 00000100
//0000100000000100
currentEntry = (currentEntry << 8); 
//000010000000010000000000
currentEntry = (currentEntry | (unsigned long long int)entryBuffer[i][j]); //entrybuffer[i][j] = 10100000
//111111111111111110100000    (what?)*****
currentEntry = (currentEntry << 8);
//11111111111111111010000000000000
currentEntry = (currentEntry | (unsigned long long int)entryBuffer[i][j]); //entrybuffer[i][j] = 11000000
//11111111111111111111111111000000

我似乎在这里遗漏了一些明显的东西,我想知道是否有人可以帮助我解决这个问题。我希望代码足够有意义。

显然,按位 OR 正在改变某些东西,或者某处发生了溢出,这就是为什么我将 currentEntry 设为 unsigned long long int。我显然只需要 4 个字节的存储空间,而且我知道这在机器之间有所不同,但是我认为 unsigned long long int 足以满足我的目的。 如果需要更多信息和上下文,请告诉我。

谢谢!

【问题讨论】:

  • 您没有在编译时启用警告是吗(例如-Wall -Wextra)? 严格别名规则?
  • 什么 entryBuffer?它的类型是什么?
  • @Some 程序员老兄 entryBuffer 是一个字符。我也在编译警告,但不是我认为的严格别名规则。
  • for 循环的第二行覆盖了currentEntry 的值,但没有引用currentEntrybitShifter 是什么?
  • 一旦你解决了这个问题 - 通过使用 0xFF 屏蔽扩展的(即强制转换的)字符,如下所示 - 然后对赋值运算符 &lt;&lt;=|= 进行一些额外的有趣学习。

标签: c bitwise-operators bit-shift bitwise-or


【解决方案1】:

char 类型可以是unsigned signed,具体取决于编译器。在你的情况下,它似乎是signed

这意味着当您将其转换为更大的类型时,您会遇到一种称为符号扩展的东西。你在二进制数中看到的所有这些都是因为这个以及two's complement(处理负数的最常见方法)的工作原理。

如果您想存储无符号的小 8 位值,请改用显式 uint8_t 类型(注意 u 前缀,代表 unsigned)。参见例如this fixed-width integer reference 了解更多信息。

【讨论】:

  • 实际上,如果 char 在扩展到 longlong 之后被 0xFF 屏蔽,它会起作用。
  • @某程序员老兄 谢谢!这样可行。今天学到了新东西。我知道它与某些东西的二进制补码有关,但是我不知道 char 类型可以是有符号的还是无符号的。我最终只是将 entryBuffer 转换为 (unsigned long long int) (uint8_t) entryBuffer[i][j]),这非常难看,但可以快速解决。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-17
相关资源
最近更新 更多