将volatile表达式的结果转换为void [英] Casting the results of a volatile expression to void

查看:319
本文介绍了将volatile表达式的结果转换为void的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

请注意

这是不一样的问题。是的,我已经阅读了许多有关投放的帖子。这些问题没有导致我怀疑这里的答案是真的。

This is Not the same thing that has been asked many times. Yes I have read the many many posts about casting to void. None of those questions resulted in the answer I suspect is true here.

背景信息:

嵌入式C.这具体与存储器映射的易失性指针相关。换句话说,外设寄存器。

Embedded C. This is specifically related to memory mapped volatile pointers. In other words, peripheral registers.

我遇到了一个涉及到写I2C外设的例程中的下面一行:

I came across the following line in a routine that involves writing to an I2C peripheral:

(void) I2C1->SR2;

I2C1 到易失性存储器。

所以这行的结果是不避免编译器警告,因为我在这里做的所有搜索的答案。它实际上导致编译器读取该寄存器(因为它是volatile),然后丢弃它。此寄存器中有标志。

So the result of this line is NOT to "avoid a compiler warning" as is the answer on all the searches I did here. It is in fact causing the compiler to read that register (since it's volatile) and then throw it away. This register has flags in it. The act of reading the register causes the flags to clear.

现在这是非常重要的,因为目标是清除标志不仅仅是避免一些编译器警告!

Now this is pretty important since the goal was to clear the flags not just avoid some compiler warning!

我担心的是,在某种程度的优化或者不同的编译器,这段代码将被优化。这是我的问题:

What has me worried however, is that at some level of optimization or maybe a different compiler, this code will get optimized away. That is my question:

这会得到优化还是有办法保证不会被优化?

Will this get optimized away or is there a way to guarantee it won't be optimized away?

我把所有的相关代码放在下面:

I put all the relevant code together below:

#define PERIPH_BASE           ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region                                */
#define APB1PERIPH_BASE       PERIPH_BASE
#define I2C1_BASE             (APB1PERIPH_BASE + 0x5400)
#define I2C1                ((I2C_TypeDef *) I2C1_BASE)
typedef struct
{
  __IO uint16_t CR1;        /*!< I2C Control register 1,     Address offset: 0x00 */
  uint16_t      RESERVED0;  /*!< Reserved, 0x02                                   */
  __IO uint16_t CR2;        /*!< I2C Control register 2,     Address offset: 0x04 */
  uint16_t      RESERVED1;  /*!< Reserved, 0x06                                   */
  __IO uint16_t OAR1;       /*!< I2C Own address register 1, Address offset: 0x08 */
  uint16_t      RESERVED2;  /*!< Reserved, 0x0A                                   */
  __IO uint16_t OAR2;       /*!< I2C Own address register 2, Address offset: 0x0C */
  uint16_t      RESERVED3;  /*!< Reserved, 0x0E                                   */
  __IO uint16_t DR;         /*!< I2C Data register,          Address offset: 0x10 */
  uint16_t      RESERVED4;  /*!< Reserved, 0x12                                   */
  __IO uint16_t SR1;        /*!< I2C Status register 1,      Address offset: 0x14 */
  uint16_t      RESERVED5;  /*!< Reserved, 0x16                                   */
  __IO uint16_t SR2;        /*!< I2C Status register 2,      Address offset: 0x18 */
  uint16_t      RESERVED6;  /*!< Reserved, 0x1A                                   */
  __IO uint16_t CCR;        /*!< I2C Clock control register, Address offset: 0x1C */
  uint16_t      RESERVED7;  /*!< Reserved, 0x1E                                   */
  __IO uint16_t TRISE;      /*!< I2C TRISE register,         Address offset: 0x20 */
  uint16_t      RESERVED8;  /*!< Reserved, 0x22                                   */
  __IO uint16_t FLTR;       /*!< I2C FLTR register,          Address offset: 0x24 */
  uint16_t      RESERVED9;  /*!< Reserved, 0x26                                   */
} I2C_TypeDef;

在某个功能中的某处....

Somewhere down in a function....

(void) I2C1->SR2;

感谢您提供任何帮助。

Thanks in advance for any help. This site has been a great resource for newbies like me.

推荐答案

volatile 关键字是便携式方式,以防止内存访问被优化和/或重新排序。应该注意,正确使用 volatile 关键字可以将表达式的结果转换为(void) 。例如,假设我已经typedef一个结构并且有一个结构的实例。

The volatile keyword is the portable way to prevent memory accesses from being optimized away and/or reordered. It should be noted that the proper use of the volatile keyword makes casting the results of the expression to (void) unnecessary. For example, let's say I've typedef'd a structure and have an instance of that structure.

typedef struct 
{
    int a;
    int b;
}
    SomeStruct;

SomeStruct test;

以下代码会导致编译器抱怨warning:expression result unused

The following code will cause the compiler to complain, "warning: expression result unused"

    SomeStruct *vptr = &test;
    vptr->a;

我可以通过将结果转换为(void),但是编译器可以自由优化读取。

I can avoid the warning by casting the result to (void), but then the compiler is free to optimize away the read.

    SomeStruct *vptr = &test;
    (void) vptr->a;

但是,如果我将指针声明为 volatile 并且不转换为(void),我不会获得警告,编译器将优化掉读。

However, if I declare the pointer as volatile and don't cast to (void), I won't get a warning and the compiler will not optimize away the read.

    volatile SomeStruct *vptr = &test;
    vptr->a;

故事的道德是,如果你使用 volatile 关键字,您应将表达式转换为(void)。这将仅抑制否则将识别缺少或不正确使用 volatile 关键字的警告。

The moral of the story is that if you are using the volatile keyword, you should not cast expressions to (void). That will only suppress warnings that would otherwise identify missing or incorrect use of the volatile keyword.

这篇关于将volatile表达式的结果转换为void的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆