Annotation Modifiers
Many annotations that must be applied to function parameters must be represented as a single macro, rather than as a series of adjacent macros. In particular, this is true for most of the various basic annotations, which should appear as a single macro for each parameter.
This is accomplished by adding modifiers to the annotation to compose a more complete annotation. The two most common modifiers, _opt and _deref, are examples of how to create more complex annotations by combining simpler annotations.
The _opt Modifier
The __in annotation does not allow NULL pointers, but often a function can take a NULL in the place of an actual parameter. The _opt modifier indicates that the parameter is optional; that is, it can be NULL. For example, an optional input parameter--such as a pointer to a structure--would be annotated as __in_opt, whereas an optional output parameter would be coded as __out_opt.
Typically, __in_opt and __out_opt are used for pointers to structures with a fixed size. Additional modifiers can be applied to annotate variable-sized objects, as described in Buffer-Size Annotations.
The _deref Modifier
User-defined types such as structures can be declared as parameter types, so it is sometimes necessary to annotate the dereferenced value of a parameter. The _deref modifier indicates that an annotation should be applied to the dereferenced value of a parameter, and not the parameter itself.
For example, consider the following function:
int myFunction(struct s **p);
When you pass a pointer such as struct s *p to a function, the memory that *p points to is passed by reference. p itself is passed by value. In this example, the p parameter is a variable of type pointer-to-s that is being passed by reference. **p is a variable of type struct s, *p is a pointer to that variable, and p is a pointer to that pointer.
In this example, the myFunction function is defined to modify *p, the pointer to the variable of type struct s. The function requires that p not be NULL. However, the function allows *p to be NULL--if *p is NULL, the function simply takes no action on *p.
Annotating p as __inout would require that *p be non-NULL. Annotating p as __inout_opt would allow p to be NULL. However, neither of these annotations correctly expresses the intended behavior of myFunction.
Adding the _deref modifier to the annotation applies __inout_opt to the proper dereferenced value of p, as shown in the following example:
int myFunction(__inout_deref_opt struct s **p);
This annotation specifies that the __opt annotation applies to *p, which is the dereferenced value of p; that is, *p can be NULL. The __opt annotation does not apply to p itself; that is, p cannot be NULL. Put another way, _deref_opt applies to the parameter that is passed by reference--*p--instead of the address of the reference--p.
The __deref modifier can appear more than once in an annotation, to indicate multiple levels of dereference. For example, __in_deref_deref_opt indicates that **p can be NULL.
Note The __null and __notnull annotations, which explicitly indicate that a particular parameter can be NULL or must not be NULL, are built in to the composite general-purpose annotations such as __inout. It is not necessary to include __null and __notnull in annotations such as the ones in this example.
Send comments about this topic to Microsoft
Build date: 5/3/2011