2016-08-25 413 views
1

以下是switch语句的一些代码。 getvalue()返回unsigned long。 有人可以解释为什么value0xffffffff按位联系。 该单元是32位。按位和无符号long与0xffffffff

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

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

不,没有人可以解释,除非你发布'值'的变量声明。 – Lundin

+0

汇编代码在典型的32位拱形(ILP32)和POSIX 64位拱形(I32LP64)上显示了哪些优化编译?你从中得知什么? – Olaf

+0

@Lundin我已经更新了这个问题。 'value'被声明为'static unsigned'。谢谢 – riverrock

回答

6

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

0xffffffff确保32位上的任何位都被清零。

0

代码用来有时也被称为“天真/马虎打字”,这意味着它将使用标准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位写入。看起来非常可疑。