MISRA C:2012 8 Rules 8.1 A Standard C environment

8.1 

程序不得违反标准C语法和约束,不得超出实现的转换限制

0232  十六进制转义序列的值在“unsigned char”类型中无法表示。

int ia = '\x4142';                    /* Message 0232 */

char 字符常量只有1个Byte大小(不考虑宽字符常量),‘\x4142’ = 16706, 超过范围了。 0-255

十六进制转义序列的值不得超过unsigned char中可表示的值的范围.

char 类型用于存储字母和标点符号之类的字符,但是在技术实现上char却是整数类型,这是因为char类型实际存储的是整数而不是字符

char grade  = 'A' ;

char grade = 65; // 这是一种不好的编程风格

令人奇怪的是,C将字符常量视为int类型而非char类型

 0233 八进制转义序列的值不得超过unsigned char中可表示的值的范围

/*PRQA S 3123,3211,3408,3610,3625,3628 ++*/

int ia = '\432';                    /* Message 0233 */

0322 'for'语句声明中使用的非法存储类说明符

for循环的第一项可以声明变量,但是只有'auto' and 'register'两个存储类说明符可以用, 'static', 'extern' or 'typedef'不可用

void foo(void)
{
    for (static int i = 0; i < 10; ++i)    /* Message 0322 */
    {
    }
}

https://blog.csdn.net/wfreehorse/article/details/60762579

 0338 八进制和16进制转义字符值超过‘unsigned char’ ‘wchar_t’所表示的范围

char *s = "\400";                    /* Message 0338 */
// \400 = 256  ; \377 = 255 
// "\400" 是一个字符数组,s[0] = '\400' , s[1] = '\0'

0422 调用函数是传参的个数 小于 函数原型指定的参数个数

int foo(int a, int b);

void test(int x)
{
    int ret;

    ret = foo(x);              /* Message 0422 */
}

0423 调用函数是传参的个数 大于 函数原型指定的参数个数

0426 被调用函数返回类型不完整

typedef struct S T1;

extern T1 s;
extern T1 foo1(int n);

void foo2(int n)
{ /* struct S 还没定义 */
    s = foo1(n);                /* Message 0426                     */
}

struct S {int a; int b;};       /* struct S is now a complete type  */

void foo3(int n)
{
    s = foo1(n);                /* OK - return type is now complete */
}

0427 该对象已被用作函数或函数指针标识符。

void foo(void)
{
    int r;
    int name;

    r = name();                 /* Message 0427 */
}

0429 一个函数的参数是算术类型,但是传进去的参数不是算术类型。

extern void foo(int p);

struct ST1 { int si; char sbuf[10];};
union  UN1 { int ui; int uj;};

extern struct ST1 st1a;
extern union  UN1 un1a;

extern int *pi;
extern int gi;


extern void test(void)
{
    foo(gi);                  /* OK           */
    foo(pi);                  /* Message 0429 */
    foo(&gi);                 /* Message 0429 */
    foo(st1a);                /* Message 0429 */
    foo(un1a);                /* Message 0429 */
}

0430 跟上一条类似,函数传参类型不匹配。

0431 函数参数指向受限类型(Function argument points to a more heavily qualified type)。

不能把const type *  传给函数参数原型为  type*  

不能把volatile type *  传给函数参数原型为  type*  

反之可以,可以把 type *  传给函数参数原型为 const  type*  

eg:

const int *a;

int *b;

b = a; // wrong

a = b; // right 指针a指向的内容不能变(不能通过指针a改变,可以通过其他指针改变),但是指针a这个地址可以变。

#include<stdio.h>

int main()
{
    const int a[3] = { 1 , 2,3 };
    const int *c = a;
    int b[3] = { 4,5,6 };
    //a = b;
    c = b;
    //c[1] = 3; // wrong
    //b = c;// wrong
    printf("%d\n", c[1]);
}

 

extern void fi(int * pi);
extern void fci(const int * pci);
extern void fvi(volatile int * pvi);
extern void fcvi(const volatile int * pcvi);

extern int *pi;
extern const int *pci;
extern volatile int *pvi;
extern const volatile int *pcvi;


void test(void)
{
    fi(pi);                   /*              */
    fi(pci);                  /* Message 0431 */
    fi(pvi);                  /* Message 0431 */
    fi(pcvi);                 /* Message 0431 */

    fci(pi);                  /*              */
    fci(pci);                 /*              */
    fci(pvi);                 /* Message 0431 */
    fci(pcvi);                /* Message 0431 */

    fvi(pi);                  /*              */
    fvi(pci);                 /* Message 0431 */
    fvi(pvi);                 /*              */
    fvi(pcvi);                /* Message 0431 */

    fcvi(pi);                 /*              */
    fcvi(pci);                /*              */
    fcvi(pvi);                /*              */
    fcvi(pcvi);               /*              */
}

 0432 函数参数不是兼容的指针类型

struct ST1 { int si; char sbuf[10];};
union  UN1 { int ui; int uj;};

extern struct ST1 st1a;
extern union  UN1 un1a;

extern char *pc;
extern char **ppc;
extern char gc;
extern char cbuf[10];
extern unsigned char *puc;

extern void foo(char * ptp);

void test(void)
{
    foo(pc);                  /* OK           */
    foo(st1a);                /* Message 0432 */
    foo(un1a);                /* Message 0432 */
    foo(gc);                  /* Message 0432 */
    foo(ppc);                 /* Message 0432 */
    foo(cbuf);                /* OK           */
    foo(puc);   /* Message 0432   'char' and 'unsigned char' (or 'signed char') are distinct types*/
}

0446 ++ / -- 操作数必须是标量

struct ST  {int a; int b;};
union  UN  {char c[4]; int x;};

extern struct ST st;
extern union  UN un;

void foo(void)
{
    st++;                       /* Message 0446 */
    un++;                       /* Message 0446 */
}

0447 ++ /  -- 的操作数必须是可修改的对象。

extern        int x[10];
extern const  int y;

void foo(void)
{
    ++x;                        /* Message 0447 */
    ++y;                        /* Message 0447 */
}

0448 ++ /  -- 的操作数不能是指向未知大小的对象的指针。

extern struct TAG *pc;
extern int (*pa)[];
extern void       *pv;

void foo (void)
{
    ++pc;               /* Message 0448 */
    ++pv;               /* Message 0448 */
    ++pa;               /* Message 0448 */
}

0449 ++ /  -- 的操作数不能是函数指针

extern void (*fn_ptr)(void);

void foo (void)
{
   ++fn_ptr;                  /* Message 0449 */
}

0450 数组类型表达式不能 类型转换

类型转换的操作数必须是标量类型(scalar type)  (A basic type, enumeration type or pointer type)

(The type char, the signed and unsigned integer types, and the floating types)

struct ST { int ai[3]; };

extern struct ST sf(void);
extern struct ST sta;
extern int       ibuf[10];

void foo(void)
{
    char *pc;

    pc = (char *)ibuf;              /* OK - ibuf decays to type pointer to int      */
    pc = (char *)(sta.ai);          /* OK - sta.ai decays to type pointer to int    */
    pc = (char *)(sf().ai);         /* Message 0450 and also 0481                   */
    pc = (char *)sta;               /* Message 0481 - sta is not of scalar type     */
}

0452 指针下标索引未知大小的对象。

extern struct ST *gx;           /* The size of struct ST is unknown */

void foo(struct ST *px)
{
   *gx = px[2];                 /* Message 0452 */
}

0454  取地址符& 不能应用于 使用'register'声明的对象

void foo (void)
{
    register int a;
    int *pa;

    pa = &a;               /* Message 0454 */
}

The address-of operator '&' cannot be applied to an object declared with the 'register' storage-class specifier.

The C language defines five storage-class specifiers: static, extern, auto, register and typedef

0456 该表达式没有地址 - “&”只能应用于左值或函数指示符。

运算符&只能应用于函数指示符或左值,不能指定 位字段 且不能 指定 寄存器存储类说明符 声明的对象。

extern int g;
extern void func(int x);

void foo(void)
{
    int *pi;
    void (*pvf)(int x);

    pi = &g;           /* Operand of & is an lvalue              */
    pvf = &func;       /* Operand of & is a function designator  */
    pvf = func;        /* & is optional on a function designator */ /* See ISO-C90 6.2.2.1 */

    pi = &(g + 1);     /* Message 0456                           */
}

0457 取地址符不能应用在位字段

位bit 可以占据 一个字节byte中的部分或者全部, & 根据字节读地址,不能精确到字节中某一位的地址。

struct flags {
   unsigned int hi:1;
   unsigned int lo:1;
   unsigned int ins:1;
   unsigned int ovr:1;
};

int main(void)
{
   struct flags f;
   int *ip;
   unsigned int i;

   f.hi = 0;
   f.lo = 0;
   f.ins = 0;
   f.ovr = 0;


   ip = &(f.hi);           /* Message 0457 */
   ip = &f.lo;             /* Message 0457 */

   i = f.ins;

   return 0;
}

https://blog.csdn.net/huasir_hit/article/details/75201126

有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几 
个不同的对象用一个字节的二进制位域来表示。 

一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为: 
  struct 位域结构名 
  { 位域列表 }; 
  其中位域列表的形式为: 类型说明符 位域名:位域长度 

 https://www.runoob.com/cprogramming/c-bit-fields.html.

#include <stdio.h>
#include <string.h>
 
/* 定义简单的结构 */
struct
{
  unsigned int widthValidated;
  unsigned int heightValidated;
} status1;
 
/* 定义位域结构 */
struct
{
  unsigned int widthValidated : 1;
  unsigned int heightValidated : 1;
} status2;
 
int main( )
{
   printf( "Memory size occupied by status1 : %d\n", sizeof(status1));
   printf( "Memory size occupied by status2 : %d\n", sizeof(status2));
 
   return 0;
}
/*当上面的代码被编译和执行时,它会产生下列结果:*/
Memory size occupied by status1 : 8
Memory size occupied by status2 : 4
/* 位域声明
在结构内声明位域的形式如下:
*/
struct
{
  type [member_name] : width ;
};
0457 取地址符不能应用在位字段

0482 Expressions may only be cast to 'void' or scalar types.

typedef struct ST { int a; } T;
typedef void (FUNC)(void);

int bar(void);

void foo(int n)
{
    T  t;

    t = (T)n;         /* Message 0482 - attempting to cast to struct type   */
    (FUNC)n;          /* Message 0482 - attempting to cast to function type */
    (void)bar();      /* OK                                                 */
}

0483 指向未知大小的对象的指针不能是加法运算符的操作数。

当进行任何一种指针的算术运算时,必须要知道指针指向对象的大小,例如,指针 加1,指针的值不是增加1,增加的是指向对象类型的大小。

extern struct ST *ps;
extern void *pv;

void foo(int n)
{
   ps = ps + n;       /* Message 483 */
   pv = pv + n;       /* Message 483 */
}

0546 枚举类型定义不完整

enum ETAG ex;                       /* Message 0546 */

void foo(void)
{
}

 

 
posted @ 2019-09-03 22:59  清风oo  阅读(1094)  评论(0编辑  收藏  举报