赋值从指针目标类型中丢弃'volatile'限定符

时间:2014-07-01 16:48:21

标签: c pointers embedded volatile

我一直在使用微处理器来读取传感器的温度,并且遇到有关挥发性声明的以下警告。

“赋值从指针目标类型中丢弃'volatile'限定符”

我收到一个温度值,在重新启动程序之前,值不会改变。

  volatile uint16_t temp_value = 0;

  if (value_type == UA_TYPE_UInt16)
  {
      data_value.value_UInt16 = &temp_value; // warning*******

      switch (handle)
      {
            case HANDLE_TEMP1:
              temp_value = ADC_GetConversionValue(ADC3);
              break;
      }
  }

在搜索堆栈溢出后,我意识到将temp_value声明为volatile将表示temp_value将更改值。我在这个网站上找不到的是为什么我不能为data_value.value_UInt16使用volatile无符号整数

我将ADC值存储在服务器中,并希望随时访问更新后的值。是否有一个额外的类型转换我应该指向temp_value?谢谢阅读。

4 个答案:

答案 0 :(得分:8)

您的volatile uint16_t temp_value对编译器说了#34;我的变量temp_value可能会被您不知道的事情所改变" (特别是,访问和写入用于存储变量的内存的其他进程)。除此之外,它还会阻止编译器进行某些优化。

当你这样做时:

data_value.value_UInt16 = &temp_value;

(我认为value_UInt16是非易变的)

您将volatile的地址分配给非易失性字段:编译器警告您允许对其进行优化,忽略可能会更改指针对象& #34;它不知道"。


解决方案:

1)Typecast data_value.value_UInt16 = *(uint16_t*)&temp_value,对编译器说:"我知道我在做什么,我知道我在这里忽略了挥发性限定符"。

或者,

2)同时将value_UInt16 volatile字段设为


重要提示:

您标记了C ++和C但是:

  • 在C ++中,这是错误(转换无效),例如here
  • 在C中,这是一个警告(你展示的那个)

答案 1 :(得分:1)

Volatile的工作方式与const的工作方式大致相同。这段代码

const int i = 1;
int* iPtr = &i; //error

无效,因为它尝试将指向const的指针指定给指向非const的指针。 类似地,

volatile int i = 1;
int* iPtr = &i; //error
除了volatile之外,

因同样的原因无效。虽然您的示例不完整,但这就是问题所在。

答案 2 :(得分:0)

您应该添加embedded标记。

除非您可以让链接器将变量分配给特定地址,否则应始终通过指针或引用访问硬件:

// Using linker notation:
volatile uint16_t temperature @ "temperature_segment";

// Using pointer, pointer to a volatile uint16_t
uint16_t volatile * temperature = 0x44000025; // Example address

// Because the variable is a pointer to a volatile value,
//    a "snapshot" copy should be made before using.
uint16_t snapshot_temperature = *temperature;
if (snapshot_temperature > 100 /* celsius */)
{
    SYSTEM_FAILURE(TEMPERATURE_OVERHEATING);
}

volatile关键字指示编译器避免优化与温度变量相关的代码。此外,由于目标值(硬件寄存器)可能会更改,因此应在进行任何比较之前进行快照复制。

答案 3 :(得分:0)

我打开了data_value.value_UInt16的声明,以找到有关该类型的更多信息,因为问题是它接受的类型不是我设置的类型等于。事实证明它只接受在另一个头文件中预定义的数据类型。

要解决这个问题,我只需查看它会接受的类型并插入其中一个,如下所示;

   typedef enum 
   {
     UA_TYPE_Invalid         = 0,  /**< Invalid type */
     UA_TYPE_Boolean         = 1,  /**< Boolean */
     UA_TYPE_SByte           = 2,  /**< signed byte */
     UA_TYPE_Byte            = 3,  /**< unsigned byte */
     UA_TYPE_Int16           = 4,  /**< signed 16 bit integer */
     UA_TYPE_UInt16          = 5,  /**< unsigned 16 bit integer */
     UA_TYPE_Int32           = 6,  /**< signed 32 bit integer */
     UA_TYPE_UInt32          = 7,  /**< unsigned 32 bit integer */
     UA_TYPE_Int64           = 8,  /**< signed 64 bit integer */
     UA_TYPE_UInt64          = 9,  /**< unsigned 64 bit integer */
     UA_TYPE_Float           = 10, /**< 32 bit single precision floating point */
     UA_TYPE_Double          = 11, /**< 64 bit double precision floating point */
     UA_TYPE_String          = 12, /**< UTF8 string */
     UA_TYPE_DateTime        = 13, /**< 64 bit signed integer containing date and time */
     UA_TYPE_Guid            = 14, /**< 16 byte long array of unsigned bytes */
     UA_TYPE_ByteString      = 15, /**< variable length array of unsigned bytes */
     UA_TYPE_XmlElement      = 16, /**< UTF8 string containing XML */
     UA_TYPE_NodeId          = 17, /**< Not supported for application */
     UA_TYPE_ExpandedNodeId  = 18, /**< Not supported for application */
     UA_TYPE_StatusCode      = 19, /**< Not supported for application */
     UA_TYPE_QualifiedName   = 20, /**< Not supported for application */
     UA_TYPE_LocalizedText   = 21, /**< Not supported for application */
     UA_TYPE_ExtensionObject = 22, /**< Not supported for application */
     UA_TYPE_DataValue       = 23, /**< Not supported for application */
     UA_TYPE_Variant         = 24, /**< Not supported for application */
     UA_TYPE_Range           = 884,/**< Not supported for application */
     UA_TYPE_EUInformation   = 887 /**< Not supported for application */
   } UA_Value_type_t;

    uint16_t server_value   = 0;

    if (value_type == UA_TYPE_UInt16)
    {
    data_value.value_UInt16 = &server_value;
    source_timestamp = my_variables[handle - 1].source_timestamp;
    status_code = my_variables[handle - 1].status_code;

    ADC_SoftwareStartConv(ADC3);