【问题标题】:integer promotion of bit-wise operation and endiannes issue按位运算和字节序问题的整数提升
【发布时间】:2018-06-13 17:21:06
【问题描述】:

考虑以下在 Linux 内核中运行的代码中的 sn-p:

    char *d;
    u32 mask, step, val;
    ...
    /* d is initialized with valid pointer pointing at buffer,
and mask, step and val are initialized to some sane values as well. */
    ...
    val = (*d & mask) >> step;

如您所见,只有dchar * 类型,其余都是无符号整数。我知道 C 会自动执行类型转换 不同类型的值参与表达式,在这种情况下 逐位运算。那么,我假设保证*d 也将被提升为uint32_t

如果这个假设是正确的,我的第二个问题将是关于位于d 指向的内存中的 4 个字节的 字节顺序。我认为它必须是主机实现的任何字节顺序,或者如果它是网络,那么严格来说是大端。

【问题讨论】:

  • 此代码 sn-p 不依赖于字节序。它确实取决于char签名
  • 它被转换为uint32_t,是的。但是具体怎么做就看有没有签名了。
  • *d 是一个字节,所以顺序无关紧要。
  • 没关系。它在编译器内部,仅用于计算。
  • 单字节 *d 将被符号扩展为 32 位或零扩展为 32 位,具体取决于 char 是否带符号。

标签: c types linux-kernel endianness integer-promotion


【解决方案1】:

因为d 具有char * 类型,它在d 指向的地址读取单个 字节。所以表达式*d 具有char 类型,它具有d 指向的字节的值。字节序在这里无关紧要,因为只从 d 读取一个字节。

在较大的表达式*d & mask 中,*d 类型为char 的值转换uint32_t 以用于表达式。

【讨论】:

  • @Mark 只有在您单独读取每个字节并且必须解释它们之后,才有意义。 *d 只从缓冲区中提取一个字节,而不是 4 个。
  • @Mark *d 是一个字节,包含一个从 -128 到 127 的值。当它被转换时,它仍然会有一个在那个范围内的值。将*d 转换为更大的类型不会自动拉出d 指向的后3 个字节。
  • @Mark 正确。它只有一个字节,所以字节序不会起作用。
  • CPU 寄存器没有字节序。一旦一个字节从内存读入寄存器,任何二进制位掩码(and-ing)和移位都会对整个寄存器的算术二进制值进行操作。
  • @Mark,很难想象一个现有的 CPU 架构在某些时候不使用表达式操作数加载其寄存器。但我的观点是整数操作数在评估表达式中没有字节顺序,只是一些位宽的二进制值。换句话说,1 << 12 将是相同的值,而与 CPU 字节序无关。字节顺序与整数表达式评估根本无关。
猜你喜欢
  • 1970-01-01
  • 2020-08-18
  • 1970-01-01
  • 2015-05-07
  • 2015-08-09
  • 2010-11-05
  • 1970-01-01
  • 2011-03-29
相关资源
最近更新 更多