繁体   English   中英

增量后取消引用指向volatile int的指针

[英]De-referencing pointer to a volatile int after increment

unsigned int addr = 0x1000;    
int temp = *((volatile int *) addr +  3);

它是否将递增的指针(即addr + 3 * sizeof(int) )视为指向volatile int (在取消引用时)的指针。 换句话说,我可以期望临时说( 0x1012 )的硬件更新内容吗?

是。

指针算术不影响指针的类型,包括任何类型限定符。 给定形式为A + B的表达式,如果A具有指向T的类型合格指针,而B是整数类型,则表达式A + B也将是指向T的合格指针-相同类型,相同限定符。

从C规范6.5.6.8(草案n1570)开始:

将具有整数类型的表达式添加到指针或从指针中减去时,结果将具有指针操作数的类型。

假设addr是具有实现可以安全地转换为int *的值的整数(变量或常量)(请参见下文)。

考虑

volatile int a[4] = [ 1,2,3,4};
int i = a[3];

除了将整数显式转换为volatile int * (指向...的指针)外,这完全相同。 对于索引操作符,所述阵列的名称衰减到的指针的第一个元素a 这是volatile int * (C中的类型限定符适用于数组的元素,而不适用于数组本身)。

这与演员表相同。 留下2个差异:

  • 将整数转换为“指针”。 这是实现定义的,因此,如果您的编译器正确支持(应对此进行记录),并且值正确,那就很好。

  • 最后进入。 基础对象不是volatile ,而是指针/ resp。 访问。 这实际上是标准中的一个缺陷(请参阅DR476 ,它要求对象是volatile ,而不是访问性。这与已记录的意图(请阅读链接)和C ++语义(应相同)相反。所有)的实现都会生成代码,并按预期执行访问。请注意,这是嵌入式系统上的一个常见概念。


因此,如果满足先决条件,则代码是正确的。 但是,请参见下文,以获得更好的(在可维护性和安全性方面)选项。


注意:更好的方法是

  • 使用uintptr_t保证整数可以容纳一个指针,或者-更好-
  • #define ARRAY_ADDR ((volatile int *)0x1000)

后者避免了对整数的意外修改,并明确说明了含义。 它也可以更容易使用。 它是底层外设寄存器定义中的典型构造。


回覆。 您的增量: addr 不是指针! 因此,您增加了一个整数,而不是一个指针。 撇开它,比使用真正的指针要输入的更多,它还容易出错,并且会使您的代码混淆。 如果需要指针,请使用指针

int *p = ARRAY_ADDR + 3;

作为个人说明:每个在至少具有某些质量标准的公司中传递此类代码(带有整数addr代码)的人都会与她的团队负责人进行认真的交谈。

首先请注意,从整数到指针的转换不一定安全。 由实现定义,将发生什么。 在某些情况下,这种转换甚至可以调用未定义的行为,以防整数值不能表示为指针,或者指针以不对齐的地址结尾。

使用整数类型uintptr_t来存储指针和地址更安全,因为可以保证能够为给定系统存储指针。

假设您的编译器对此代码实现了安全的转换(例如,大多数嵌入式系统编译器都执行了此操作),那么该代码的确会按预期运行。

指针运算将在volatile int类型上进行,因此+ 3表示将地址增加sizeof(volatile int) * 3个字节。 如果系统上的int为4字节,则最终将读取地址0x100C的内容。 不确定从哪里获得0x1012 ,将十进制和十六进制表示法混在一起?

暂无
暂无

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

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