【问题标题】:Type casting pointer dereference类型转换指针取消引用
【发布时间】:2016-04-18 21:52:17
【问题描述】:

整理一个退休工程师的代码,我遇到了一个相当简单的宏,但是我的 C 知识不是很好。

#define mem32(addr) (*(unsigned long volatile *)(addr)) 
  1. 我是否正确地将其称为类型转换指针取消引用?
  2. 它类型转换 addr 然后取消引用它?还是反过来?有关系吗?
  3. 类型限定符和类型说明符的顺序是否重要?我曾假设(在此之前)类型限定符必须在类型说明符之前,但事实并非如此
  4. 语法问题。第二个 * 的目的是什么?

【问题讨论】:

    标签: c pointers casting dereference


    【解决方案1】:
    1. 我是否正确地将其称为类型转换指针取消引用?

    是的。

    1. 它类型转换 addr 然后解除它?还是反过来?有关系吗?

    *(unsigned long volatile *)(addr) 正在对addr 进行类型转换,然后取消引用它。

    1. 类型限定符和类型说明符的顺序是否重要?

    没有。顺序无所谓。 C11 节 §6.7.2/2

    [...] 类型说明符可以以任何顺序出现,可能 与其他声明说明符混合。 [...]

    【讨论】:

    • 谢谢。 volatile 类型限定符后面的 * 怎么样?我以前见过,但不明白它的目的。
    • unsigned long volatile * 是类型指向unsigned long volatile int的指针的声明说明符。
    【解决方案2】:

    演员 (unsigned long volatile *)(addr) 发生在取消引用之前。

    不,unsignedlongvolatile 的顺序无关紧要只要没有其他运算符混入。 IE。 volatile int*int volatile* 是相同的,但 int * volatile 是不同的。

    在高层次上,这个宏的目的是获取任何指针,并从该内存地址读取前四个字节。

    但是,如果传递给 mem32 的指针既不是指向 longchar 的指针,则会调用未定义的行为!这是由于严格的别名规则。旧的编译器过去常常安全地为这个宏生成预期的代码,但是如果现代编译器证明类型不匹配,他们可能只是使用那个宏来优化代码。所以,不要在新代码中使用它。

    【讨论】:

      猜你喜欢
      • 2020-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-05
      • 2021-12-03
      • 2019-05-23
      • 1970-01-01
      相关资源
      最近更新 更多