MISRA C-2012 Rule 11.3 violation while trying to do a typecast from char to int pointer

跟風遠走 提交于 2020-05-30 07:53:23

问题


I am trying to get rid of Rule 11.3 from my code.

Sample code:

static int32_t 
do_test(const char *cp)
{
    const char *c = cp;
    const int32_t *x;
    x = (const int32_t *)cp;

    return *x;
}

I want the value of *c and *x to be same. Even-though the code is compiling and giving the correct value, "x = (int32_t *)cp;" causing violation of 11.3 and 11.8

Rule 11.3 violation: An object with pointer type shall not be converted to a pointer to a different object type.

I have tried with void pointer, but the result was not same as what I expected and also it resulted in additional violation.

Is there anyway to remove these violations ?

From MISRA C 2012 Document they are mentioning like there is an exception for this rule as it is permitted to convert a pointer to object type into a pointer to one of the object types char, signed char or unsigned char. The Standard guarantees that pointers to these types can be used to access the individual bytes of an object.

Ignore Dir 4.6 due to char type.


回答1:


You are lucky you are using MISRA-C, because this code is full of bugs. You cannot make the bugs go away with a cast.

  • Bug 1. The character pointer is not necessarily aligned, in which case your code invokes undefined behavior as per the C standard 6.3.2.3/7:

    A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned for the referenced type, the behavior is undefined.

  • Bug 2. The code contains a blatant strict aliasing violation. This is always undefined behavior as per the C standard 6.5/7.

    Your assumption "The Standard guarantees that pointers to these types can be used to access the individual bytes of an object." is correct: as a special exception C allows you to convert from a pointer-to-x to pointer to char and then access the data through the char poiner. But not the other way around.

    Your code is not accessing individual bytes; you are going the other way around, from an array of characters to a 32 bit type. This is not allowed. See What is the strict aliasing rule?.


Correct code, that should be ok with both the C language and MISRA-C:

static int32_t do_test(const char *cp)
{
  return (int32_t) ((uint32_t)cp[0] << 24u) |
                   ((uint32_t)cp[1] << 16u) |
                   ((uint32_t)cp[2] <<  8u) |
                   ((uint32_t)cp[3]);
}

This shift version is always preferred, as it is endianess independent and therefore portable. The casts to uint32_t are necessary to prevent implicit promotions on 8/16 bit systems, plus you should never do bit shift on signed types.




回答2:


If you feel a need to avoid the explicit cast, you can always do memcpy:

#include <string.h>
#include <stdint.h>

static int32_t 
do_test(const char *cp)
{
    int32_t r;
    memcpy(&r,cp,sizeof(r));
    return r;
}

With an optimizing compiler that has a builtin mempcy, this should be just as efficient as return *(int32_t*)cp; (your code, written more succinctly).

Keep in mind that in either case, the code is only defined if the cp value you passed in points to a valid int32_t object.

If memcpy isn't OK because of the implicit char* to void* cast, you could replace it with a custom-made trivially implemented void charwise_memcpy(char *Dest, char const *Src, size_t Sz); or the equivalent for loop.

void charwise_memcpy(char *Dest, char const *Src, size_t Sz)
{
    for(size_t i=0; i<Sz; i++)
        Dest[i]=Src[i];
}



回答3:


The original code may cause undefined behaviour:

const char *cp;
// ...
x = (const int32_t *)cp;

If int32_t has an alignment requirement on the platform, and cp is not correctly aligned for that requirement, the behaviour is undefined.

I'm not a fan of MISRA in general but this particular instance seems well justified. Even if you happen to be on a platform with no alignment requirements (unlikely even in embedded development), this code is non-portable and might start breaking if you move to a CPU that does have alignment requirements.

A good solution is to use memcpy instead which is well-defined:



来源:https://stackoverflow.com/questions/47617615/misra-c-2012-rule-11-3-violation-while-trying-to-do-a-typecast-from-char-to-int

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!