我觉得这个短语应该是declaration linker specifier的缩写。在MSDN官网上的解释是:__declspec是用于对指定的存储类信息的扩展。其实这和上面的翻译并不矛盾,因为内存地址的生成实在链接期间生成,而并非编译的时候生成的。因为static和extern是C/C++标准的一部分,所以不属于__declspec的部分。
支持__declspec扩展的特性语法的关键字如下所示:align、allocate、appdomain、deprecated、dllexport、dllimport、jitintrinsic、naked、noalias、noinline、noreturn、nothrow、novtable、process、restrict、safebuffers、selectany和thread,以及为支持COM对象属性而存在的property和uuid。
其实很多语法通过简单地英语翻译过来就可以理解意思了。下面解释下:__declspec(extend_decl_modifier_seq),这是__declspec的语法。
(1)__declspec(align(16))与#pragma pack是一对。前者规定了对齐的最小值,后者规定了对齐的最大值。两者同时出现的时候,__declspec优先级更高。
(2)__declspec(allocate())必须跟在#pragma code_seg(data_seg)等数据段之后。例如
#pragma data_seg(”segname“)\
__declspec(allocate(”segname“))int i=0;
\#pragma data_seg()
表明i变量被分配到在segname数据段当中。
(3)__declspec(appdomain)MSDN的解释是:在指定托管应用程序下的每一个应用程序都应该有托管应用程序的全局变量和静态成员变量的副本。(也就是指定的托管应用程序的全局变量和静态变量是不共享的)。
(4)__declspec(deprecated)identity表明在同一个作用于内,不能出现identity。否则会出现C4996警告。
(5)__declspec(dllexport)和__declspec(dllimport)不再多说
(6)__declspec(jitinsrinsic)从名字翻译来看,和C#有关。可能是利用C#内置的JIT属性吧(MSDN解释也不很详细,其实上面的appdomain也带一点蒙的味道,对C#不太懂,希望高手补充)。
(7)__declspec(naked)表明程序在转化为汇编语句的时候,由程序员自己控制,而不是编译器来优化。这里可以用于实现DLL的stub,直接jmp到某一个位置,然后再call调用。
(8)__declspec(noalias)MSDN的解释是函数只会改变局部变量,而不会引起全局的变化,对上层可能的改变时参数指针所指向的位置。
(9)__declspec(noinline)告诉链接器不要内联一个函数。
(10)__declspec(noreturn)表明函数不返回,当然也说明函数是不可达的。除非程序出了错。
(11)__declspec(nothrow)表明声明的函数绝不会抛出异常。
(12)__declspec(nobtable)阻止编译器为类别生成构造虚拟函数表的函数——也就是构造函数。当然个属性只能用在接口上面。因为纯虚函数不会有实例,所以也就没有构造函数。
(13)__declspec(process)和__declspec(thread)类似,都是指明自身对进程/线程的数据有单独的拷贝。其中__declspec(thread)有一个很牛的学名叫做TLS。正因为线程需要额外的定义来实现TLS,所以微软鼓励使用C的线程库,也就是_beginthread函数。
(14)__declspec(restrict)适用于返回指针的函数,表明不会返回当前程序中已经被使用的别名指针。
(15)__declspec(safebuffers)VS的新特性,会生成溢出检测,也就是说发生溢出攻击的时候程序可能会崩溃或者出现非预期的结果。
(16)__declspec(selectany)使得我们可以在.h头文件当中顶一个全局变量。并且即使我们多次包含这个头文件,也不会出现多重定义的错误。
(17)__declspec(uuid)和__declspec(property)用于COM对象属性,为COM组件添加相应的UUID和属性值。其实和QT下面的Q_PROPERTY宏。