Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
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