批注概述
函数可以利用批注来显式声明行为。 开发人员可以将功能性批注嵌入源代码中,以显式声明“实现”(被调用方)和“客户端”(调用方)之间的协定。 代码分析工具使用函数调用前后的函数参数和返回类型的条件等附加信息,检测是否存在违反调用方与被调用方之间的协定的情况。 如果在函数声明上指定批注,则无需在函数定义上指定批注。
特性
批注架构是作为 VC++ 编译器特性实现的。 下面两个特性提供了批注的基础:
Pre
Pre 特性的每个实例为批注参数指定一组属性。 下面的批注使用具有 Valid 属性的 Pre 特性:
void f ( [ Pre (Valid = Yes) ] int pWidth);
通过对参数 pWidth 进行批注,函数要求调用方返回一个有效的整数值。 对于整数(或浮点)值,这意味着参数已经初始化,且不包含垃圾数据。
Post
Post 特性的每个实例为批注参数或返回值指定一组属性。 下面的批注使用具有 MustCheck 属性的 Post 特性:
[returnvalue:Post(MustCheck=Yes)] bool f();
通过对函数的返回值进行批注,要求调用方检查函数的返回值;因此,类似如下的调用将生成 C6031:
void main( )
{
// code
f ( ); // warning 6031
// code
}
除了 Pre 特性和 Post 特性,还有以下两个特性可供使用:
FormatString 特性,用于指定格式信息。 它用于 Style 属性。
InvalidCheck 特性,用于确定函数的返回值是否有效。 它用于 Value 属性。
属性
有几个可以使用 Pre 和 Post 特性指定的属性。 虽然大多数属性可以在 Pre 和 Post 特性上使用,但 MustCheck 属性只能应用于函数的返回值,且必须使用 Post 特性指定。 使用特殊属性之前,应阅读相关文档,以了解特性及其支持的数据类型。 有关更多信息,请参见 批注属性。
在 C 中使用批注
若要在 C 源文件中使用批注,请包括以下文件:
#include <CodeAnalysis/SourceAnnotations.h>
下一步,对函数进行批注,如下面的代码所示:
void f ([ SA_Pre (Valid = SA_Yes) ] int pWidth );
注意 在 C 代码中,必须在特性和枚举值中使用 SA_ 前缀。
在 C++ 中使用批注
在 C++ 中,在添加 #include <CodeAnalysis/SourceAnnotations.h> 文件之后添加下面的命名空间:
using namespace vc_attributes;
下一步,对函数进行批注,如下面的代码所示:
void CMyClass::f ([ Pre (Valid = Yes) ] int pWidth )
提示
在 C++ 代码中,无需对枚举值使用 SA_ 前缀,例如 Yes、No 和 Maybe。 但是,在将要同时用于 C 和 C++ 代码的标头中,则必须使用 SA_ 前缀。 在 C++ 中,派生类不能继承批注。