从指针或引用中抛弃常量/易失性



这是我代码的一部分...
正如我在下面所做的那样,我知道铸造是正确的,但我的逻辑得到了 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参数,并且您无缘无故地从中删除了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);
}

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

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

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

问题是你正在抛弃恒常性。如果您只是要使用 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)。

> 由于问题被标记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

最新更新