繁体   English   中英

为什么硬件寄存器访问是通过无符号数据类型

[英]Why hardware register access is through unsigned datatype

我正在阅读一些例子,并且在所有这些例子中都使用了unsigned。 如果使用正确,使用int类型是否安全? 与下面的示例类似,0x12345678地址将写入0xFFFFFFFF,而不管ptr被定义为有符号还是无符号。

volatile unsigned int* ptr = (volatile unsigned int* ) 0x12345678; 

*ptr = 0xFFFFFFFF;

为什么使用unsigned而不是signed来进行寄存器访问是否安全?

我认为无符号C算法更接近机器寄存器算术。 这是因为C语言定义说,如果有符号整数算术运算结果为不符合给定类型(溢出)的数字,则操作的实际结果是未定义的。 所以它可以是任何东西。 在无符号算术中:

涉及无符号操作数的计算永远不会溢出,因为无法用结果无符号整数类型表示的结果以比模式生成的无符号整数类型所表示的最大值大1的数量减少。

这与机器寄存器中发生的情况相同。

你的例子是另一种情况,即:

*ptr = 0xFFFFFFFF;

创建一个类型为unsigned long int的常量0xFFFFFFFF 类型是unsigned而不是int因为该值大于最大整数值。 如果变量ptr的类型为int* ,则编译器需要在赋值之前将unsigned转换为signed 这会导致溢出,并且此赋值的结果将是未定义的。 虽然我不知道在从unsignedint时会生成任何算术运算的编译器。

如果ptr被定义为int* ,并且你想要正确,那么你的行应该是:

*ptr = -1;

大多数硬件寄存器要么不是算术对象(它们可能是位字段而不是语义数字),或者如果它们确实代表一个数字,那么对它们进行语义签名是不常见的(例如,负值对波特率除数没有意义) )。

通常,虽然签名类型在低级别上可能没有区别,但它在高级别上没有语义意义。

或许,通常用于处理硬件寄存器值的>>运算符具有已签名类型的实现定义行为; 因此,为了避免混合符号操作以及引入错误的关联隐式转换,您应该在大多数情况下使用unsigned。

我建议除非硬件寄存器是语义符号数字,否则你应该不仅对寄存器一致地使用无符号,而且还要在带有寄存器操作数的表达式中使用操作数。

答案很简单:您使用的值是无符号的(意味着文字0xFFFFFFFF是无符号的)。 您可以将其分配给任何可以保存它的数据类型 - 甚至可以使用float或double。 但是,您希望存储无符号值并将其视为无符号值(例如,printf的%x说明符,它打印十六进制值,将其强制转换为无符号值)。 那么,如果您的数据在整个过程中未签名,为什么不将其容器的数据类型也取消签名呢?

您写入的处理器寄存器不知道或不关心编译器如何定义值,只要写入正确的值即可。 我赞成这个问题,因为你试图在发布之前找到答案。

如前所述,未签名或签名以相同的方式存储在硬件寄存器中。 更高级别的c将此值解释为有符号或无符号数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM