【问题标题】:Mini questions on 'unsigned char' and 'shift' operation?关于“unsigned char”和“shift”操作的小问题?
【发布时间】:2012-09-24 00:36:55
【问题描述】:

这个问题应该是基本的,但我很惊讶我现在遇到了一些麻烦。第一个是当我浏览“C++ 入门”一书第 5.3 章时。位运算符,当作者使用下面的代码作为例子来解释移位操作时:

unsigned char bits = 1;     // '10011011' is the corresponding bit pattern
bits << 1;                  // left shift

当我看到这个时,我有点头晕,“10011011”是从哪里来的? “1”不是“0x01”?

另一个问题来自http://c-faq.com/strangeprob/ptralign.html,作者尝试解压结构:

struct mystruct {
    char c;
    long int i32;
    int i16;
} s;

使用

unsigned char *p = buf;

s.c = *p++;

s.i32 = (long)*p++ << 24;
s.i32 |= (long)*p++ << 16;
s.i32 |= (unsigned)(*p++ << 8);  // this line !
s.i32 |= *p++;

s.i16 = *p++ << 8;
s.i16 |= *p++;

我的问题是,p 是指向 unsigned char(8 位)的指针,对吧?在构建 s.i32(24~31, 16~23) 的更高字节时,*p++ 在左移之前会转换为 'long'(32bits),因此左移不会在 *p++ 中丢失位,而是在

s.i32 |= (unsigned)(*p++ << 8);

*p++先移位,再转为unsigned int,移位过程中*p++的位不就全部丢失了吗?

我再次意识到我可能在这里遗漏了一些 C 语言的基础知识。希望有人可以在这里伸出援手。

谢谢,

【问题讨论】:

  • 而字符 '1' 将是 0x31 = 00110001,所以不可能这样。
  • 第一个,你检查勘误表(什么版本)? (这类书经常出错)
  • 这是第 4 版。我会检查在线是否有任何勘误表。谢谢。
  • @user1559625:在errataPage 155: In the example at the bottom of the page the initializer for bits should be 0233, not 1.
  • 谢谢杰西!这更有意义。

标签: c++ c


【解决方案1】:

要回答您的第二个问题,对 char 执行 any 算术运算会将其提升为(可能是无符号的)int(包括移位和其他按位运算),因此整数大小值被移位,而不是 8 位 char 值。

【讨论】:

  • 更准确地说,你需要控制提升到你想要的类型位移;不是之后。
  • @CraigNelson 是的,关于符号扩展/无符号。
  • 完全正确。这就是我试图向他传达的内容(你显然已经知道 =P)
【解决方案2】:

是的,1 的位模式是 0x01。 10011011 是十进制 155 的位模式。

至于移位,您缺少一种称为“积分提升”的东西,它在算术和二进制运算中执行,例如移位。在这种情况下,有一个unsigned char 操作数(*p++)和一个int 操作数(常量),所以unsigned char 操作数被转换为int。转换(无论是long 还是unsigned int)总是在升级和轮班执行之后执行。所以不,在任何一次移位中都没有丢失所有的位。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-02
    • 2012-11-18
    • 1970-01-01
    • 2012-04-10
    • 1970-01-01
    • 2023-02-10
    • 2016-04-04
    • 2012-11-19
    相关资源
    最近更新 更多