[英]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.