【问题标题】:assignment discards 'volatile' qualifier from pointer target type赋值从指针目标类型中丢弃 'volatile' 限定符
【发布时间】:2014-07-01 16:48:20
【问题描述】:

我一直在使用微处理器从传感器读取温度,并遇到以下关于易失性声明的警告。

"赋值从指针目标类型中丢弃 '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 吗?谢谢阅读。

【问题讨论】:

  • 您注意到代码中的小& 符号了吗?
  • 显示value_UInt16的类型定义。应该是volatile uint16_t *value_UInt16
  • 您是否尝试过添加类型转换? data_value.value_UInt16 = *(uint16_t*)&temp_value

标签: c pointers embedded volatile


【解决方案1】:

你的volatile uint16_t temp_value 对编译器说“我的变量temp_value 可能会被你不知道的东西改变”(特别是其他进程访问和写入用于存储变量的内存)。除其他外,它会阻止编译器进行某些优化。

当你这样做时:

data_value.value_UInt16 = &temp_value;

(我假设value_UInt16 是非易失性的)

您将 volatile 的地址分配给非易失性字段:编译器警告您允许对其进行优化,忽略指针对象可能会“被事物改变”它不知道”。


解决方案:

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

或者,

  1. value_UInt16 也设为volatile 字段

重要提示:

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

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

【讨论】:

  • 感谢 quantdev。您正确假设, value_UInt16 是非易失性的,当我通过输入将其声明为易失性时;易失性值_UInt16; if 语句前的一行我收到以下警告;在“value_UInt16”的声明中,类型默认为“int”。
【解决方案2】:

Volatile 的工作方式与 const 基本相同。这段代码

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

无效,因为它试图将指向 const 的指针分配给指向非 const 的指针。 同样,

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

出于同样的原因无效,但 volatile 除外。尽管您的示例不完整,但这就是问题所在。

【讨论】:

    【解决方案3】:

    您应该添加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 关键字指示编译器不要优化与温度变量相关的代码。此外,由于目标值(硬件寄存器)可能会发生变化,因此在进行任何比较之前应制作快照副本。

    【讨论】:

      【解决方案4】:

      我打开了 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);
      

      【讨论】:

      • 这只是一个解决方案,如果你错误地认为你需要“volatile”
      猜你喜欢
      • 1970-01-01
      • 2011-03-29
      • 1970-01-01
      • 1970-01-01
      • 2016-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-19
      相关资源
      最近更新 更多