__declspec语法
__declspec(align(n)) n字节对齐和pragram pack一样
前者最大值,后者对齐最小值__declspec(deprecated )说明一个函数,类型,或别的标识符在新的版本或未来版本中不再支持,你不应该用这个函数或类型。它和#pragma deprecated作用一样。
后面跟函数__declspec( allocate(“segname”) )要和pragma的ode_seg, const_seg, data_seg,section,init_seg配合使用。
感觉好复杂,先放放用declspec(dllexport),declspec(dllimport)显式的定义dll接口给调用它的exe或dll文件,用 dllexport定义的函数不再需要(.def)文件声明这些函数接口了。
注意:若在dll中定义了模板类那它已经隐式的进行了这两种声明,我们只需在 调用的时候实例化即可,呵呵。declspec( naked )
对于没有用naked声明的函数一般编译器都会产生保存现场(进入函数时编译器会产生代码来保存ESI,EDI,EBX,EBP寄存器 ——prolog)和清除现场(退出函数时则产生代码恢复这些寄存器的内容——epilog) 代码,而对于用naked声明的函数一般不会产生这些代码,这个属性对于写设备驱动程序非常有用,我们自己可以写这样一个过程,它仅支持x86 。naked只对函数有效,而对类型定义无效。对于一个标志了naked的函数不能产生一个内联函数即时使用了forceinline 关键字。__declspec(restrict) ,restrict 说明函数返回值没有被别名化,返回的指针是唯一的,没有被别的函数指针别名花,也就是说返回指针还没有被用过是唯一的。编译器一般会去检查指针是否可用和 是否被别名化,是否已经在使用,使用了这个关键字,编译器就不在去检查这些信息了。
- 可以理解为和编译器做了一个君子协定(只针对指针函数),返回的指针值绝对不会在当前程序使用的(别名)
__declspec(noalias) 也是仅适用于函数,它指出该函数是半纯粹的函数。半纯粹的函数是指仅引用或修改局部变量、参数和第一层间接参数。
- 网上说不能用全局变量或第二层间接指针参数,但测试没错误。实在不明白呢!
__declspec(noinline)
告诉编译器不去内联一个具体函数。(记得.h文件的定义是默认内联的)declspec(noreturn)
告诉编译器没有返回值.注意添加declspec(noreturn)到一个不希望返回的函数会导致已没有定义错误.__declspec(nothrow)
用于函数声明,它告诉编译器函数不会抛出异常。
- 这个和函数后面加throw()这个君子协定一样
_declspec(novtable)
用在任意类的声明,但是只用在纯虚接口类,因此这样的不能够被自己实例话.它阻止编译器初始化虚表指针在构造和析构类的时候,这将移除对关联到类的虚表的 引用.如果你尝试这实例化一个有novtable关键字的类,它将发生AV(access violation)错误.C++里virtual的缺陷就是vtable会增大代码的尺寸,在不需要实例化的类或者纯虚接口的时候,用这个关键字可以减 小代码的大小.
- 我想它只用于纯虚基类。因为这样可以减少虚表的空间。
测试了下,然而并没有什么卵用。sizeof依旧。。
记个代码
#if _MSC_VER >= 1100 && !defined(_DEBUG)//这个条件判断可以学习
#define AFX_NOVTABLE __declspec(novtable)
#else
#define AFX_NOVTABLE
#endif
declspec(selectany)可以让我们在.h文件中初始化一个全局变量而不是只能放在.cpp中。比如有一个类,其中有一个静态变量,那 么我们可以在.h中通过类似” declspec(selectany) type class::variable = value; “这样的代码来初始化这个全局变量。既是该.h被多次include,链接器也会为我们剔除多重定义的错误。这个有什么好处呢,我觉得对于 teamplate的编程会有很多便利。
declspec(thread) 用于声明一个线程本地变量它告诉编译器,对应的变量应该放入可执行文件或DLL文件中它的自己的节中。declspec(thread)后面的变量 必须声明为函数中(或函数外)的一个全局变量或静态变量。不能声明一个类型为__declspec(thread)的局部变量。我想可能和volatile有点关系
uuid__declspec(uuid)
用于编译器关联一个GUID到一个有uuid属性的类或结构的声明或者定义.
: __stdcall : | : __cdecl : | : __fastcall : | |
---|---|---|---|
参数传递 | 右->左 压栈 | 右->左 压栈 | 左边开始的两个不大于4字节(DWORD)的参数分别放在ECX和EDX寄存器,其余的参数仍旧自右向左压栈传送 |
清理栈方 | 被调用函数清理(即函数自己清理) | 调用者清理 | 被调用者清理栈 |
适用场合 | Win API | c/C++ MFC默认方式可变参数的时候使用 | 速度快 |
pragram语法
所有的预处理指令中,#pragma 指令可能是最复杂的了
/#ifdef _X86
/#pragma message(“_X86 macro activated!”)
/#endif
当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示
“_X86 macro activated!”
这样,我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了。/#pragma hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译。
/#pragma warning指令
该指令允许有选择性的修改编译器的警告消息的行为
once:只显示一次(警告/错误等)消息
default:重置编译器的警告行为到默认状态
1,2,3,4:四个警告级别
disable:禁止指定的警告信息
error:将指定的警告信息作为错误报告
pragma warning( push )保存所有警告信息的现有的警告状态。
/#pragma warning( push, n)保存所有警告信息的现有的警告状态,并且把全局警告等级设定为n。
/#pragma warning( pop )向栈中弹出最后一个警告信息,在入栈和出栈之间所作的一切改动取消。pragma comment(…) 很多,具体自己查吧,反正就用了几个。
pragma code_seg( [ [ { push | pop}, ] [ identifier, ] ] [ “segment-name” [, “segment-class” ] )