【问题标题】:what does it mean to bitwise left shift an unsigned char with 16将无符号字符按位左移 16 是什么意思
【发布时间】:2012-05-31 16:29:48
【问题描述】:

我正在读取一个包含 unsigned char 变量的 .cpp 文件,它正在尝试按位左移 16 位,因为 unsigned char 由 8 位组成,左移 16 位将擦除所有位并用八个 0。

unsigned char byte=0xff; byte << 16;

【问题讨论】:

标签: c++ c bit-manipulation


【解决方案1】:

当你移动一个值时,

unsigned char x = ...;
int y = x << 16;

如果unsigned char 适合int(大多数系统),则x 的类型提升为int,如果unsigned char 不适合int,则提升为unsigned(罕见1)。只要您的int 为 25 位宽或更宽,则不会丢弃任何数据2。

请注意,这与16 具有int 类型这一事实完全无关。

/* All three are exactly equivalent */
x << 16;
x << 16u;
x << (unsigned char) 16;

来源:来自 n1516(C99 草案):

§6.5.7 第 3 段:按位移位运算符

对每个操作数执行整数提升。结果的类型是 提升的左操作数。

§6.3.1.1 第 2 段:布尔值、字符和整数

如果一个 int 可以表示原始类型的所有值(受宽度限制,对于一个 位域),该值被转换为一个整数;否则,将其转换为无符号 诠释。这些称为整数促销。

脚注:

1:已知某些 DSP 芯片以及某些 Cray 超级计算机具有sizeof(char) == sizeof(int)。这以增加内存消耗为代价简化了处理器的加载存储单元的设计。

2:如果你的左移提升为int,然后溢出int,这是未定义的行为(恶魔可能会飞出你的鼻子)。相比之下,unsigned 的溢出始终是明确定义的,因此位移位应该通常在 unsigned 类型上完成。

【讨论】:

  • 非常感谢您的详尽解释。尽管我仍然对将unsigned char 升级为int 后可能会意外覆盖的内存感到困惑
  • @leomayleomay:这不是它的工作原理。如果将int 分配给unsigned char 变量,则int 将被转换。 (毕竟这不是汇编语言。)
  • 所以这里的按位左移(向左 16)将使有问题的变量为 0,对吧?
  • 如果您分配x = x &lt;&lt; 16,那么在大多数系统上,这与x = 0 相同。
  • 我发现这种行为非常令人惊讶。我使用 IAR CSTAT 静态分析工具对以下代码遇到了这样的行为: unsigned short BE2LE16(unsigned short x) { return ((x>8));} 并且无法弄清楚直到你的详细回答。非常感谢您和 IAR!
【解决方案2】:

如果char 适合int,它将被提升为int,结果将如您所愿。如果不是这种情况,则根据标准它是未定义的行为,并且可能会发出编译警告。来自标准:

The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.

【讨论】:

  • 如果char 不适合int,它永远不会导致未定义的行为,因为它必须适合unsigned int,并且unsigned int 上的移位永远不会未定义。只有带符号整数的移位是未定义的,并且仅当数学结果不能由该类型表示时。例如,如果 int 是 16 位,则 1 &lt;&lt; 16 未定义。
  • 确实执行了整数提升,这意味着只有当 unsigned char 提升为 int 而不是 unsigned int 并且移位将产生一个无法在一个int。
猜你喜欢
  • 1970-01-01
  • 2011-04-07
  • 2014-05-11
  • 1970-01-01
  • 1970-01-01
  • 2022-12-22
  • 1970-01-01
  • 2010-09-29
相关资源
最近更新 更多