【问题标题】:cast away const/volatile from a pointer or reference从指针或引用中丢弃 const/volatile
【发布时间】:2014-01-27 10:30:35
【问题描述】:

这是我的代码的一部分...
正如我在下面所做的那样,我知道铸造是正确的,但我收到了我的逻辑的 linting 警告.. 你能解释一下为什么会这样吗..
我的部分代码:

typedef struct
{
    char  appid[4];                  /**< application id */
    int32 pid;                      /**< process id of user application */
} DApplication;

static int32 d_cmp(const void *m1, const void *m2)
{
    DApplication *mi1 = (DApplication *) m1;   //Line 1
    DApplication *mi2 = (DApplication *) m2;   //Line 2
    return memcmp(mi1->appid, mi2->appid, 4);  //Line 3
}

And warnings are :                      
Sample.cpp (line 1):Note 960: Violates MISRA 2004 Required Rule 11.5, attempt to cast away const/volatile from a pointer or reference
Sample.cpp (line 2):Note 960: Violates MISRA 2004 Required Rule 11.5, attempt to cast away const/volatile from a pointer or reference
Sample.cpp (line 3):Note 960: Violates MISRA 2004 Required Rule 10.1, Implicit conversion changes signedness

...Courtsey MISRA
As per the MISRA rule :                                              Rule 11.5 (required): A cast shall not be performed that removes any const or volatile
qualification from the type addressed by a pointer.
[Undefined 39, 40]
Any attempt to remove the qualification associated with the addressed type by using casting is a
violation of the principle of type qualification. Notice that the qualification referred to here is not
the same as any qualification that may be applied to the pointer itself.

uint16_t x;
uint16_t * const cpi = &x; /* const pointer */
uint16_t * const * pcpi; /* pointer to const pointer */
const uint16_t * * ppci; /* pointer to pointer to const */
uint16_t * * ppi;
const uint16_t * pci; /* pointer to const */
volatile uint16_t * pvi; /* pointer to volatile */
uint16_t * pi;
...
pi = cpi; /* Compliant - no conversion
no cast required */
pi = (uint16_t *)pci; /* Not compliant */
pi = (uint16_t *)pvi; /* Not compliant */
ppi = (uint16_t * *)pcpi; /* Not compliant */
ppi = (uint16_t * *)ppci; /* Not compliant */                        

SO According to this rule i think it is fine 

【问题讨论】:

  • 为什么你认为选角合适?你正在抛弃const
  • void* 这不是真正的C++ =)
  • 那么正确的投射方式是什么??
  • 铸造将是const DApplication *mi1 = reinterpret_cast&lt;const DApplication*&gt; m1;。但这仍然不是正确的 C++。
  • @Ashwin 如果您确定 m1m2 实际上指向非 const 对象,则应将函数参数指定为 void *,而不是 const void *。而且,另一个大问题当然是你为什么要使用void...(但这与 constness 问题无关)。

标签: c++ lint


【解决方案1】:

据我所知,铸造是正确的,正如我在下面所做的那样......

为什么你认为你的选角是“合适的”?您有 const 参数,并且您完全没有理由从它们中删除 const-ness。您系统上的memcmp() 参数类型是什么?它们应该是 const 指针 - 来自 http://en.cppreference.com/w/cpp/string/byte/memcmp

int memcmp( const void* lhs, const void* rhs, std::size_t count );

所以,你可以像这样修复你的函数:

static int32 d_cmp(const void* m1, const void* m2)
{
    return memcmp(static_cast<const DApplication*>(m1)->appid,
                  static_cast<const DApplication*>(m2)->appid,
                  sizeof DApplication().appid);
}

【讨论】:

    【解决方案2】:

    之所以这样,是因为你在玩火。您没有使用类型系统,而是在规避它。在 C++ 中有很多更好的方法可以做到这一点,例如:

    static int32 d_cmp(const DApplication *m1, const DApplication *m2)
    

    const DApplication *mi1 = static_cast<const DApplication *>(m1);
    

    【讨论】:

      【解决方案3】:

      问题是你正在抛弃 constness。如果您只想使用 memcmp,则无论如何都不需要这样做,因为它需要 (const void*, const void*, size_t)

      试试这个:

      #include <cstring> // memcmp
      
      typedef struct {
          char appid[4];                /**< application id */
          int pid;                      /**< process id of user application */
      } DApplication;
      
      static int d_cmp(const void *m1, const void *m2)
      {
          const DApplication *mi1 = static_cast<const DApplication *>(m1);   //Line 1
          const DApplication *mi2 = static_cast<const DApplication *>(m2);   //Line 2
          return memcmp(mi1->appid, mi2->appid, 4);  //Line 3
      }
      
      int main(void)
      {
          DApplication a1 = {{0,0,0,0}, 1};
          DApplication a2 = {{0,0,0,1}, 1};
      
          return d_cmp(&a1, &a2);
      }
      

      记得用 c++ 编译器编译它(使用g++ 而不是gcc)。

      【讨论】:

      • 当我尝试使用相同的语句时,它显示语法错误..缺少什么..
      • 与老式演员的唯一区别是 const 受到尊重。这意味着不能使用 reinterpret_cast 将 const 对象转换为非 const 对象。 codingunit.com/c-tutorial-typecasting-part-1 出现以下错误:一行缺少多个标记;语法错误
      • 那里,添加了完整的例子。
      【解决方案4】:

      由于问题被标记为C++,这里有点像 C++ 解决方案。

      此解决方案通过消除强制转换解决了问题,并且还使代码更简洁、更安全,并且可能更快。

      1. 您可以使用匿名命名空间代替static
      2. 您可以使用函数模板来保持类型安全(如果您需要不同的类型。如果不需要,只需硬编码DApplication)。
      3. 无需使用指针。请改用参考文献。
      4. 使用 std::array 而不是 C 样式的数组。它提供operator==() 方便(并且更有可能更快)逐元素比较,因此无需memcmp

        struct DApplication
        {
            std::array <char, 4> appid;
            int pid;
        };
        
        struct NotDApplication
        {
            int foo;
        };
        
        namespace {
            template <typename T>
            bool CompareAppIds(const T& mi1, const T& mi2)
            {
                return (mi1.appid == mi2.appid);
            }
        }
        
        int main()
        {
            DApplication a, b;
            NotDApplication c, d;
        
            bool isEqual = CompareAppIds(a, b);  // OK
        
            bool isEqual2 = CompareAppIds(c, d); // Compile error: 
                                                 // 'appid' : is not a member
                                                 // of 'NotDApplication'
        }
        
      5. 此外,如果合适,您可以将 operator==() 重载为 DApplication

      【讨论】:

        猜你喜欢
        • 2012-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-12
        相关资源
        最近更新 更多