C++ Primer 笔记——固有的不可移植的特性

1.为了支持底层编程,C++定义了一些固有的不可移植的特性,所谓不可移植特性是指因机器而异的特性。

 

2.一个位域中含有一定数量的二进制位,位域在内存中的布局是机器相关的。位域的类型必须是整型或枚举类型,因为带符号位位域的行为是由具体实现确定的,所以在通常情况下我们使用无符号类型保存一个位域。

typedef unsigned int Bit;
class test
{
    Bit A : 2;    // A占2位
    Bit B : 1;    // B占1位
    Bit C : 3;    // C占3位
};

如果可能的话,在类的内部连续定义的位域压缩在同一整数的相邻位,从而提供存储压缩。这些是与机器相关的。

3.取地址运算符不能作用于位域,因此任何指针都无法指向类的位域。

 

4.访问位域的方式:

typedef unsigned int Bit;
class test
{
public:
    Bit A : 2;    // A占2位
    Bit B : 1;    // B占1位
    Bit C : 3;    // C占3位
};

test t;

t.A |= 0xFF;    // A=3
t.B = 1;        // B=1
t.C &= 0x00;    // C=0


 

5.volatile表示对象的值可能在程序的控制或检测之外被改变,并告诉编译器不应该对这样的对象进行优化。voilatile起到对类型额外修饰的作用。

class test{};

volatile int i;            // 该int值可能发生改变
volatile int* p;        // p指向一个volatile对象
volatile int arr[2];    // arr的每个元素都是volatile
volatile test t;        // t的每个成员都是volatile

 

6.const和volatile限定符互相没什么影响,某种类型可能既是const的也是volatile的,此时它同时具有二者的属性。

 

7.就像一个类可以定义const成员函数一样,它也可以将成员函数定义成volatile的,只有volatile的成员函数才能被volatile的对象调用。

 

8.和const一样,我们只能将一个volatile对象的地址赋值给一个指向volatile的指针,只有当某个引用是volatile的时,我们才能使用一个volatile对象初始化该引用。

volatile int i;                // i是一个volatile int
int *volatile ip;            // ip是一个volatile指针,指向int
volatile int* p;            // p是一个指针,指向volatile int
volatile int *volatile vp;    // vp是一个volatile指针,它指向一个volatile int

int *p1 = &i;    // 错误,必须使用只想volatile的指针
p = &i;            // 正确
vp = &v;        // 正确


9.const和volatile的一个重要区别是我们不能使用合成的拷贝/移动构造函数及赋值运算符初始化volatile对象或从volatile对象赋值。因为合成的成员接受的形参是非volatile常量引用,显然我们不能把一个非volatile引用绑定到一个volatile对象上。

 

10.C++ 使用链接指示指出任意非C++函数所用的语言。想要把C++代码和其他语言编写的代码放在一起使用,要求我们必须有权访问该语言的编译器,并且这个编译器与当前的C++编译器是兼容的。

 

11.链接指示不能出现在类定义或函数定义的内部。同样的链接指示必须在函数的每个声明中都出现。

extern "C" size_t strlen(const char*);    // 单语句链接指示

extern "C"    // 复合语句链接指示
{
    int strcmp(const char&, const char*);
    char *strcat(char*, const char*);
}


12.多重声明的形式可以应用于整个头文件。头文件中所有普通函数声明都被认为是由链接指示的语言编写的,链接指示可以嵌套,因此如果头文件包含自带链接指示的函数,则该函数的链接不受影响。

extern "C"    
{
    #include <string.h>
}


13.当我们使用链接指示时,它不仅对函数有效,而且对作为返回类型或形参类型的函数指针也有效。

// func是一个C函数,它的形参是一个指向C函数的指针
extern "C"    void func(void(*)(int));


14.因为链接指示同时作用于声明语句中的所有函数,所以如果我们希望给C++传入一个指向C函数的指针,则必须使用类型别别名。

extern "C"    typedef void func(int);
void f(func *);


15.通过使用链接指示对函数进行定义,我们可以令一个C++函数在其它语言编写的程序中可用。但是要注意类型限制。

extern "C"    int add(int) {}        // add 函数可以被C程序调用


16.有时候需要在C和C++中编译同一个源文件,我们可以使用预处理定义__cplusplus。

#ifdef __cplusplus
extern "C"
#endif
int strcmp(const char*, const char*);


17.链接指示与重载函数的相互作用依赖于目标语言。如果目标语言支持重载函数,则为该语言实现链接指示的编译器很可能也支持重载这些C++的函数。如果在一组重载函数中有一个是C函数,则其余的必定都是C++函数。

 

posted @ 2017-09-02 17:00  MyCPlusPlus  阅读(298)  评论(0编辑  收藏  举报