快捷搜索:   服务器  安全  linux 安全  MYSQL  dedecms

嵌入式C++编程准则

    A.     代码从C语言到C++语言的移植

    A.1     字符常量

    注解

    在C中,字符常量是int类型,而在C++中,其类型为char.

    示例

    I = sizeof(‘a’);

    在C中,i保存的实际内容是sizeof(int)的计算结果值,该值要比1大。而在C++中,i存储的实际内容是sizeof(char),该值总是为1.

    准则

    当将C代码移植为C++代码时,所有对字符常量的sizeof有依赖关系的表达式都要被移除。

    A.2     文件范围内的对象声明

    注解

    在C++中,在文件范围内,声明一个没有指定存储类型标志符的对象时,实际上是定义该对象为外部链接符号(extern)。如果这个定义中没有初始化表达式,那么该对象将被初始化为0.相比较于C来说,C++程序中声明的对象会被明确的定义且只定义过1次。

    而在C中,这将被视为一个暂时的定义,这种定义方式在一个translation unit中允许出现多次。

    示例

int a;          /* (1) */
int a = 10;     /* (2) */

    在C中,(1)是一种暂时性的定义。由于(2)被看作是确切的定义,(1)被看作是只是声明一个变量。

    在C++中,(1)、(2)都被认为是定义式。由于存在(1)、(2)两个重复定义式,因此是一个错误。

    准则

    在C++中,如果想在文件范围内仅声明一个对象(而不是定义该对象),那么该对象不能拥有初始化表达式,并且需要使用extern来修饰。

    声明于文件范围内的每一个对象只能显式的被定义一次。除了一次声明外,其余所有声明都必须具有extern修饰并且没有初始化表达式。

    A.3   const 类型修饰符

    注解

    在C中,在文件范围内,一个使用const修饰而未指明存储类型的对象具有外部链接属性。而在C++中,它具有内部连接属性。

    示例

          +- file1 --------------------+
          |      extern const int n;   |
          +----------------------------+
          +- file2 --------------------+
          |      const int n = 10;     |
          +----------------------------+
    在C中,文件file2中的对象n具有外部连接属性,因此,文件file1中对象n(该对象同样具有外部链接属性)可以引用它。在C++中,文件file2中的对象n具有的属性是内部链接的,因此,file1中的对象n无法引用到它。

    准则

    使用extern显示修饰const对象,使该对象具有外部链接属性。

    A.4    void*的转型

    注解C语言标准允许void*转换为T*(T表示任何对象),而在C++中没有这样的标准。在C++中类似的转换需要显示转换来完成。

    下面这些C标准库函数都返回void*:

    calloc, malloc, realloc, bsearch, memcpy, memmove,

    memchr, memset

    在C++中,将这些函数的返回值赋值给一个非void*的指针时,需要显示转换。

    示例

    int* p;

    p = malloc(10 * sizeof(int));

    在C++中,对指针p的赋值需要显示的转换,如:

    p = (int *)malloc(10 * sizeof(int));

    准则

    在C++中使用new来代替calloc、malloc、realloc(参考A.12);

    忽略memcpy, memmove, 以及memset的返回值(通常这些返回值由函数的第一个参数转换而来);对于其他所有返回void*函数(包括标准库函数和用户自定义函数),需要使用显式的转换来将返回值转换为其他指针类型。

    A.5   枚举类型

    注解

    C中的枚举变量是整型。程序中,枚举类型和整型可以互相转换,而不需要显式的转换。C程序允许枚举类型对象进行++和——运算。

    C++中的枚举是一种用户自定义类型。C++标准允许枚举类型转换为整型,但从整型转换为枚举类型是非法的。C++程序中还不能将内置的++和—以及符合运算符(如+=)作用于枚举类型变量上。

    示例

    enum RGB { red, green, blue } rgb;

    ++rgb;

    如果表达式(++rgb)采用内置的++运算符,那么在C++中这是一个错误表达式。该表达式的语意相当于:

    rgb = rgb + 1;

    上面的表达式在C++中还是错误的。而像下面这样,对枚举值进行显示的转换就是正确的:

    rgb = RGB(rgb + 1);

    最好的解决方法是为枚举类型RGB实现一个++运算符。

    RBG &operator++(RGB &x)

    {

    return x = RGB(x + 1);

    }

    准则

    将C程序移植为C++程序时,在需要的时候,要为枚举类型实现类型安全的++和——操作符。

    A.6    在转型、参数声明、sizeof中定义类型

    注解

    在C中,转型表达式、参数声明以及sizeof表达式中都可以进行类型声明,而在C++中则不能。

    示例

    void func(struct TAG { int a; } st)

    {

    ……

    }

    如上所示,TAG在参数声明是被定义。

    准则

    把在参数中声明的类型的定义式,挪到函数声明式作用域开始处,或者大于该作用域的某处。

    在转型和sizeof表达式作用域开始处,或者大于该作用域的某处定义类型。

    A.7   忽略局部对象定义式的控制流程跳转

    注解

    在C中,goto和switch语句可以使控制流程跳过块作用域内的局部对象声明式,甚至有可能是对象的初始化式。而在C++中不存在这种跳转。

    示例goto LABEL;

    {

    int v = 0;

    ……

    LABEL:

    ……

    }

    在C中,上面的代码是合法的,它假设标签LABEL之后的代码不依赖于整型变量v的初值0.而在C++中,这段代码总是不能通过编译。

    准则

    确保goto或switch语句没有跳过局部对象的初始化式。

    A.8   字符数组的初始化

    注解

    在C中,允许使用字符串来初始化一个字符数组。初始化表达式中,数组可以比字符串少一个字符空间(‘\0’字符)。在C++中数组则必须能完全容纳字符串。

    示例

    char s[3] = "abc";

    尽管常量字符串为4个字符大小,但数组s的大小为3.这种做法在C中合法,而在C++中非法。

    准则

    为了容纳‘\0’,请确保字符数组大小要比字符串长度大1.因而,有必要将字符数组大小指定为字符串长度+1.(也即:char s[4] = "abc";)

    然而,为了使定义式自适应于不同的常量字符串,在定义式中不指定数组大小不失为一种好方法(即:char s[] = "abc";)。

    A.9   原型声明

    注解

    C++程序要求在使用函数之前必须声明该函数原型。此外,C++程序会将函数声明式f()解释为f(void)——不带参数的函数。而在C中,这样的行为是不确定的。

    示例

    extern void func();

    ……

    sub();

    func(0);

    因为没有sub函数的声明,因此调用该函数是错误的。由于声明式中函数不带参数,因此以0为参数调用func也是个错误。

    准则

    确保被调用的函数已经被声明。为了强调函数f不带参数,好的做法是在声明函数时,将参数声明为void,即声明式为:f(void)。


    A.10 C++增加的关键字

    注解

    C中没有下面的C++关键字:

           asm             bool            catch           class
          const_cast      delete          dynamic_cast    explicit
          false           friend          inline          mutable
          namespace       new             operator        private
          protected       public          reinterpret_cast
          static_cast     template        this            throw
          true            try             typeid          typename
          using           virtual         wchar_t

    示例

    int class

顶(0)
踩(0)

您可能还会对下面的文章感兴趣:

最新评论