microsoft c++(118)

__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” ] )

// //