1、extern "C":
因为C++和C对编译后的函数符号和外部变量符号修饰方式不一样。加上这个,使其修饰的变量或函数是按照C语言方式编译,连接器才能正确解析。
在DL显式链接中,被修饰的函数就要加上这个,不然在调用的时候,函数名就要写成经C++编译器修饰过后的函数名。而不同C++编译器修饰方法也可能不同,所以还是加上这个比较方便。
2、CALLBACK,WINAPI和AFXAPI
在头文件windef.h中
#define CALLBACK __stdcall
#define WINAPI __stdcall
#define WINAPIV __cdecl
#define APIENTRY WINAPI
在头文件AFXVER_.H中
// AFXAPI is used on global public functions
#ifndef AFXAPI
#define AFXAPI __stdcall
#endif
__stdcall是自动清栈,__cdecl手动清栈。他们进栈顺序都是从右到左。
windows规定,由它调用的函数必须定义为__stdcall函数,比如回调函数,WinMain函数。
没有显式声明,函数调用方法默认为__cdecl。
3、字符串的sizeof
char s[]="12345";
strlen():5
sizeof():6
char *s="12345";
strlen():5
sizeof():4 应该是指针的原因
string s="12345"
strlen(s.c_str):5
sizeof(s.c_str):4
sizeof(s):32 string对象除了字符串还包含了其他许多东西。
4、内联函数和宏函数
1、内联函数在编译时展开,宏函数预编译展开
2、内联函数有类型检测、语法判断等,宏函数没有
3、内联函数是函数,宏函数不是,只是做文本替换
5、new、malloc与虚函数
new会调用构造函数,构造虚函数表入口地址
malloc都不会
所以用malloc如果调用虚函数就会出错
6、类的构造函数的执行顺序
class A
{
public:
A()
{
cout << "A" << endl;
}
};
class B
{
public:
B()
{
cout << "B" << endl;
}
};
class Parants
{
public:
Parants()
{
cout << "Parants" << endl;
}
A a;
};
class Son:public Parants
{
public:
Son()
{
cout << "Son" << endl;
}
B b;
};
int main()
{
Son s;
return 0;
}
可以看出来构造函数的执行顺序是:
基类对象成员的构造函数->基类的构造函数->派生类对象成员的构造函数->派生类的构造函数
7、多线程和多进程
进程:资源分配的最小单位,有独立的地址空间。
线程:CPU调度的最小单位,没有独立的地址空间。
多进程:创建进程开销比较大,通信方式复杂,比较安全。
多线程:创建线程开销比较小,通信方式简单,但是要考虑同步问题。
线程通信:全局变量、发消息、事件等。
进程通信:WM_COPYDATA、共享内存、剪贴板、SOCKET、DLL等。
8、volatile
单独写一篇文章