【问题标题】:bitwise anding unsigned long with 0xffffffff [closed]使用 0xffffffff 按位与无符号长 [关闭]
【发布时间】:2016-08-25 10:40:58
【问题描述】:

下面是 switch 语句的一些代码。 getvalue() 返回一个 unsigned long。 有人可以解释为什么value0xffffffff 按位与运算。 单片机是 32 位的。

#define WriteMemory(A,V) *(volatile unsigned long*)(A)=(V)
static unsigned value;

case 'b':
value = getvalue();
value &= 0xffffffff;
WriteMemory(2147455555, value);
break; 

【问题讨论】:

  • 不,除非你发布value的变量声明,否则没人能解释。
  • 对于典型的 32 位架构 (ILP32) 和 POSIX 64 位架构 (I32LP64) 上的优化编译,汇编代码显示了什么?你怎么理解?
  • @Lundin 我已经更新了这个问题。 value 被声明为 static unsigned。谢谢

标签: c bit-manipulation


【解决方案1】:

unsigned long 不保证 C 标准是 32 位的。它只保证能够保存 32 位值。

并使用0xffffffff 确保超过 32 位的任何位都被清零。

【讨论】:

    【解决方案2】:

    代码使用有时被称为“幼稚/草率打字”的东西,这意味着它使用标准 C 中的基本 intlong 类型。这些类型存在问题并且通常不可移植,因为它们具有实现定义尺寸。

    由于实现定义的大小,他们迂腐地屏蔽了低 32 位,以防 int 出于某种原因在某些特殊系统上变成 64 位。

    但是,专业程序始终使用来自stdint.h 的已知大小和符号类型。对于专业的嵌入式系统尤其如此。

    同样的代码可以用更安全和可移植的方式重写:

    #include <stdint.h>
    
    #define WriteMemory(A,V) ( *(volatile uint32_t*)(A)=(V) )
    static uint32_t value;
    
    case 'b':
    value = getvalue();
    WriteMemory(2147455555, value);
    break; 
    

    uint32_t 解决了所有问题:各种类型的大小不再有任何疑问,因此用低 32 位进行掩码完全是多余的。鉴于这是一个 32 位系统,您也不必担心隐式类型提升。

    (请注意宏中的额外括号,这是避免经典宏运算符优先级错误所必需的,例如x = WriteMemory(2147455555, value) + y; 错误:写入value+y,这可能不是故意的。)

    这里另一个更大的问题是,给定的系统是否允许在地址 2147455555 处进行未对齐的 32 位写入。看起来很可疑。

    【讨论】:

      猜你喜欢
      • 2016-07-05
      • 2021-10-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-28
      • 2016-12-08
      • 2023-04-05
      • 2021-06-09
      相关资源
      最近更新 更多