zoukankan      html  css  js  c++  java
  • 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] = ''

    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
    ", 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
    ", sizeof(status1));
       printf( "Memory size occupied by status2 : %d
    ", 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)
    {
    }
     
  • 相关阅读:
    BZOJ 1191 HNOI2006 超级英雄hero
    BZOJ 2442 Usaco2011 Open 修建草坪
    BZOJ 1812 IOI 2005 riv
    OJ 1159 holiday
    BZOJ 1491 NOI 2007 社交网络
    NOIP2014 D1 T3
    BZOJ 2423 HAOI 2010 最长公共子序列
    LCA模板
    NOIP 2015 D1T2信息传递
    数据结构
  • 原文地址:https://www.cnblogs.com/focus-z/p/11456302.html
Copyright © 2011-2022 走看看