批注函式參數和傳回值
本文說明簡單函式參數的註釋一般用法,即純量,以及結構和類別的指標,以及大部分種類的緩衝區。 本文也會說明註釋的常見使用模式。 如需與函式相關的其他批註,請參閱 標註函式行為。
指標參數
對於下表中的批注,當指標參數加上批注時,分析器會在指標為 Null 時報告錯誤。 此批註適用於指標和指向的任何數據項。
註釋和描述
_In_
標註純量、結構、結構指標等的輸入參數。 明確可用於簡單的純量。 參數在預先狀態中必須有效,且不會修改。
_Out_
標註純量、結構、結構指標等的輸出參數。 請勿將此批注套用至無法傳回值的物件,例如,以傳值方式傳遞的純量。 參數不一定要在前置狀態中有效,但必須在後置狀態中有效。
_Inout_
為函式變更的參數標註。 它必須同時在前置狀態和後置狀態中有效,但假設在呼叫前後具有不同的值。 必須套用至可修改的值。
_In_z_
做為輸入之 Null 終止字串的指標。 字串必須處於前置狀態。 具有正確批注的
PSTR
變體是慣用的。_Inout_z_
將修改之 Null 終止字元陣列的指標。 呼叫前後必須有效,但假設值已變更。 可以移動 Null 終止符,但只能存取原始 Null 終止符的專案。
_In_reads_(s)
_In_reads_bytes_(s)
函式所讀取之陣列的指標。 數位大小元素,
s
所有元素都必須有效。變數
_bytes_
會以位元組為單位來提供大小,而不是元素。 只有當大小不能以元素表示時,才使用此變體。 例如,只有在使用 的類似函式時,char
字串才會使用_bytes_
wchar_t
變體。_In_reads_z_(s)
陣列的指標,其為 Null 終止且具有已知大小。 最多為 Null 終止符的專案,或者
s
如果沒有 Null 終止符,則必須在前置狀態中有效。 如果大小以位元組為單位已知,請依專案大小進行調整s
。_In_reads_or_z_(s)
以 Null 終止或具有已知大小的陣列指標,或兩者皆為 。 最多為 Null 終止符的專案,或者
s
如果沒有 Null 終止符,則必須在前置狀態中有效。 如果大小以位元組為單位已知,請依專案大小進行調整s
。 (用於strn
家庭。_Out_writes_(s)
_Out_writes_bytes_(s)
函式將寫入之元素陣列的
s
指標(resp. bytes)。 陣列元素不一定在前置狀態中有效,且在後置狀態中有效的元素數目未指定。 如果參數類型上有批注,則會在後置狀態中套用批注。 例如,試想下列程式碼。typedef _Null_terminated_ wchar_t *PWSTR; void MyStringCopy(_Out_writes_(size) PWSTR p1, _In_ size_t size, _In_ PWSTR p2);
在此範例中,呼叫端會為 提供 項目的
size
p1
緩衝區。MyStringCopy
讓其中一些元素有效。 更重要的是,上的_Null_terminated_
PWSTR
批注表示p1
在後狀態中以 Null 終止。 如此一來,有效元素的數目仍然定義良好,但不需要特定項目計數。變數
_bytes_
會以位元組為單位來提供大小,而不是元素。 只有當大小不能以元素表示時,才使用此變體。 例如,只有在使用 的類似函式時,char
字串才會使用_bytes_
wchar_t
變體。_Out_writes_z_(s)
元素陣列的
s
指標。 元素不一定在前置狀態中有效。 在後置狀態中,透過 Null 終止符的元素必須有效。 如果大小以位元組為單位已知,請依專案大小進行調整s
。_Inout_updates_(s)
_Inout_updates_bytes_(s)
數位的指標,在函式中讀取和寫入。 其大小
s
為元素,且在狀態前和後置狀態中有效。變數
_bytes_
會以位元組為單位來提供大小,而不是元素。 只有當大小不能以元素表示時,才使用此變體。 例如,只有在使用 的類似函式時,char
字串才會使用_bytes_
wchar_t
變體。_Inout_updates_z_(s)
陣列的指標,其為 Null 終止且具有已知的大小。 透過 Null 終止符向上的項目必須同時在前置狀態和後置狀態中有效。 假設處於後置狀態的值與處於前置狀態的值不同;包含 Null 終止符的位置。 如果大小以位元組為單位已知,請依專案大小進行調整
s
。_Out_writes_to_(s,c)
_Out_writes_bytes_to_(s,c)
_Out_writes_all_(s)
_Out_writes_bytes_all_(s)
元素陣列的
s
指標。 元素不一定在前置狀態中有效。 在後置狀態中,最多到c
-th 元素的項目必須有效。_bytes_
如果大小以位元組而非元素數目來已知,則可以使用變數。例如:
void *memcpy(_Out_writes_bytes_all_(s) char *p1, _In_reads_bytes_(s) char *p2, _In_ int s); void *wordcpy(_Out_writes_all_(s) DWORD *p1, _In_reads_(s) DWORD *p2, _In_ int s);
_Inout_updates_to_(s,c)
_Inout_updates_bytes_to_(s,c)
數位的指標,由函式讀取和寫入。 其大小
s
為元素,所有元素都必須在前置狀態中有效,且c
元素在後置狀態中必須有效。變數
_bytes_
會以位元組為單位來提供大小,而不是元素。 只有當大小不能以元素表示時,才使用此變體。 例如,只有在使用 的類似函式時,char
字串才會使用_bytes_
wchar_t
變體。_Inout_updates_all_(s)
_Inout_updates_bytes_all_(s)
陣列的指標,由size
s
元素的函式讀取和寫入。 定義為相當於:_Inout_updates_to_(_Old_(s), _Old_(s)) _Inout_updates_bytes_to_(_Old_(s), _Old_(s))
換句話說,緩衝區中
s
每個存在於預先狀態的專案在前置狀態和後置狀態中都是有效的。變數
_bytes_
會以位元組為單位來提供大小,而不是元素。 只有當大小不能以元素表示時,才使用此變體。 例如,只有在使用 的類似函式時,char
字串才會使用_bytes_
wchar_t
變體。_In_reads_to_ptr_(p)
陣列的指標,該陣列
p - _Curr_
(也就是p
減號_Curr_
)是有效的表達式。 之前的p
元素必須處於前置狀態。例如:
int ReadAllElements(_In_reads_to_ptr_(EndOfArray) const int *Array, const int *EndOfArray);
_In_reads_to_ptr_z_(p)
表達式 (也就是
p
減號_Curr_
) 為有效表達式之 Null 終止陣列p - _Curr_
的指標。 之前的p
元素必須處於前置狀態。_Out_writes_to_ptr_(p)
陣列的指標,該陣列
p - _Curr_
(也就是p
減號_Curr_
)是有效的表達式。 之前p
的專案不一定要在前置狀態中有效,而且在後置狀態中必須有效。_Out_writes_to_ptr_z_(p)
Null 終止陣列的指標,
p
也就是p - _Curr_
減號_Curr_
)是有效的表達式。 之前p
的專案不一定要在前置狀態中有效,而且在後置狀態中必須有效。
選擇性指標參數
當指標參數註釋包含 _opt_
時,它表示參數可能是 Null。 否則,批注的行為會與不包含 _opt_
的版本相同。 以下是指針參數批註的變體清單 _opt_
:
_In_opt_
_Out_opt_
_Inout_opt_
_In_opt_z_
_Inout_opt_z_
_In_reads_opt_
_In_reads_bytes_opt_
_In_reads_opt_z_
_Out_writes_opt_
_Out_writes_opt_z_
_Inout_updates_opt_
_Inout_updates_bytes_opt_
_Inout_updates_opt_z_
_Out_writes_to_opt_
_Out_writes_bytes_to_opt_
_Out_writes_all_opt_
_Out_writes_bytes_all_opt_
_Inout_updates_to_opt_
_Inout_updates_bytes_to_opt_
_Inout_updates_all_opt_
_Inout_updates_bytes_all_opt_
_In_reads_to_ptr_opt_
_In_reads_to_ptr_opt_z_
_Out_writes_to_ptr_opt_
_Out_writes_to_ptr_opt_z_
輸出指標參數
輸出指標參數需要特殊表示法來釐清參數和指向位置的 Null 性。
註釋和描述
_Outptr_
參數不能是 Null,而且在後置狀態中,指向位置不能是 Null,而且必須有效。
_Outptr_opt_
參數可能是 Null,但在後置狀態中,指向位置不能是 Null 且必須有效。
_Outptr_result_maybenull_
參數不能為 Null,而且在後置狀態中,指向位置可以是 Null。
_Outptr_opt_result_maybenull_
參數可以是 Null,而且在後置狀態中,指向位置可以是 Null。
在下表中,會將其他子字串插入註釋名稱中,以進一步限定批註的意義。 各種子字串為
_z
、、_COM_
_buffer_
、_bytebuffer_
、 和_to_
。
重要
如果您要標註的介面是 COM,請使用這些批註的 COM 形式。 請勿將 COM 批注與任何其他類型介面搭配使用。
_Outptr_result_z_
_Outptr_opt_result_z_
_Outptr_result_maybenull_z_
_Outptr_opt_result_maybenull_z_
傳回的指標具有
_Null_terminated_
註釋。_COM_Outptr_
_COM_Outptr_opt_
_COM_Outptr_result_maybenull_
_COM_Outptr_opt_result_maybenull_
傳回的指標具有 COM 語意,這就是為什麼它帶有
_On_failure_
傳回指標為 Null 的後置條件。_Outptr_result_buffer_(s)
_Outptr_result_bytebuffer_(s)
_Outptr_opt_result_buffer_(s)
_Outptr_opt_result_bytebuffer_(s)
傳回的指標指向大小
s
專案或位元組的有效緩衝區。_Outptr_result_buffer_to_(s, c)
_Outptr_result_bytebuffer_to_(s, c)
_Outptr_opt_result_buffer_to_(s,c)
_Outptr_opt_result_bytebuffer_to_(s,c)
傳回的指標指向大小
s
元素或位元組的緩衝區,其中第一個c
是有效的。
某些介面慣例假設輸出參數在失敗時會為 Null。 除了明確 COM 程式代碼之外,下表中的表單是慣用的。 針對 COM 程式代碼,請使用上一節所列的對應 COM 窗體。
_Result_nullonfailure_
修改其他批注。 如果函式失敗,結果會設定為 null。
_Result_zeroonfailure_
修改其他批注。 如果函式失敗,結果會設定為零。
_Outptr_result_nullonfailure_
如果函式成功,傳回的指標會指向有效的緩衝區,如果函式失敗,則為 null。 此批注適用於非選擇性參數。
_Outptr_opt_result_nullonfailure_
如果函式成功,傳回的指標會指向有效的緩衝區,如果函式失敗,則為 null。 此批註適用於選擇性參數。
_Outref_result_nullonfailure_
如果函式成功,傳回的指標會指向有效的緩衝區,如果函式失敗,則為 null。 此批註適用於參考參數。
輸出參考參數
參考參數的常見用法是輸出參數。 針對簡單的輸出參考參數,例如 int&
, _Out_
提供正確的語意。 不過,當輸出值為 之類的 int *&
指標時,之類的 _Outptr_ int **
對等指標批注不會提供正確的語意。 若要簡潔地表達指標類型的輸出參考參數語意,請使用下列複合批注:
註釋和描述
_Outref_
結果在後置狀態中必須有效,而且不能為 Null。
_Outref_result_maybenull_
結果在後置狀態中必須有效,但在後狀態中可能是 Null。
_Outref_result_buffer_(s)
結果在後置狀態中必須有效,而且不能為 Null。 指向大小
s
專案的有效緩衝區。_Outref_result_bytebuffer_(s)
結果在後置狀態中必須有效,而且不能為 Null。 指向大小
s
位元組的有效緩衝區。_Outref_result_buffer_to_(s, c)
結果在後置狀態中必須有效,而且不能為 Null。 指向元素的
s
緩衝區,其中第一個c
元素有效。_Outref_result_bytebuffer_to_(s, c)
結果在後置狀態中必須有效,而且不能為 Null。 指向第一個
c
有效位元組的s
緩衝區。_Outref_result_buffer_all_(s)
結果在後置狀態中必須有效,而且不能為 Null。 指向有效元素大小的
s
有效緩衝區。_Outref_result_bytebuffer_all_(s)
結果在後置狀態中必須有效,而且不能為 Null。 指向有效元素位元組
s
的有效緩衝區。_Outref_result_buffer_maybenull_(s)
結果在後置狀態中必須有效,但在後狀態中可能是 Null。 指向大小
s
專案的有效緩衝區。_Outref_result_bytebuffer_maybenull_(s)
結果在後置狀態中必須有效,但在後狀態中可能是 Null。 指向大小
s
位元組的有效緩衝區。_Outref_result_buffer_to_maybenull_(s, c)
結果在後置狀態中必須有效,但在後狀態中可能是 Null。 指向元素的
s
緩衝區,其中第一個c
元素有效。_Outref_result_bytebuffer_to_maybenull_(s,c)
結果在後置狀態中必須有效,但在後置狀態中可能是 Null。 指向第一個
c
有效位元組的s
緩衝區。_Outref_result_buffer_all_maybenull_(s)
結果在後置狀態中必須有效,但在後置狀態中可能是 Null。 指向有效元素大小的
s
有效緩衝區。_Outref_result_bytebuffer_all_maybenull_(s)
結果在後置狀態中必須有效,但在後置狀態中可能是 Null。 指向有效元素位元組
s
的有效緩衝區。
傳回值
函式的傳回值類似於 _Out_
參數,但位於不同層級的去參考,而且您不需要考慮結果的指標概念。 針對下列批注,傳回值是批注物件:純量、結構的指標或緩衝區的指標。 這些批註的語意與對應的 _Out_
註釋相同。
_Ret_z_
_Ret_writes_(s)
_Ret_writes_bytes_(s)
_Ret_writes_z_(s)
_Ret_writes_to_(s,c)
_Ret_writes_maybenull_(s)
_Ret_writes_to_maybenull_(s)
_Ret_writes_maybenull_z_(s)
_Ret_maybenull_
_Ret_maybenull_z_
_Ret_null_
_Ret_notnull_
_Ret_writes_bytes_to_
_Ret_writes_bytes_maybenull_
_Ret_writes_bytes_to_maybenull_
格式化字串參數
_Printf_format_string_
表示參數是用於printf
表達式的格式字串。範例
int MyPrintF(_Printf_format_string_ const wchar_t* format, ...) { va_list args; va_start(args, format); int ret = vwprintf(format, args); va_end(args); return ret; }
_Scanf_format_string_
表示參數是用於scanf
表達式的格式字串。範例
int MyScanF(_Scanf_format_string_ const wchar_t* format, ...) { va_list args; va_start(args, format); int ret = vwscanf(format, args); va_end(args); return ret; }
_Scanf_s_format_string_
表示參數是用於scanf_s
表達式的格式字串。範例
int MyScanF_s(_Scanf_s_format_string_ const wchar_t* format, ...) { va_list args; va_start(args, format); int ret = vwscanf_s(format, args); va_end(args); return ret; }
其他常見的註釋
註釋和描述
_In_range_(low, hi)
_Out_range_(low, hi)
_Ret_range_(low, hi)
_Deref_in_range_(low, hi)
_Deref_out_range_(low, hi)
_Deref_inout_range_(low, hi)
_Field_range_(low, hi)
參數、欄位或結果介於 從
low
到hi
的範圍(內含) 中。 相當於_Satisfies_(_Curr_ >= low && _Curr_ <= hi)
套用至批注物件以及適當的預先狀態或后狀態條件。重要
雖然名稱包含 「in」 和 「out」 ,但和
_Out_
的_In_
語意不適用於這些批注。_Pre_equal_to_(expr)
_Post_equal_to_(expr)
註記正好
expr
是 。 相當於_Satisfies_(_Curr_ == expr)
套用至批注物件以及適當的預先狀態或后狀態條件。_Struct_size_bytes_(size)
適用於結構或類別宣告。 表示該型別的有效物件可能大於宣告型別,且所
size
指定的位元元組數目。 例如:typedef _Struct_size_bytes_(nSize) struct MyStruct { size_t nSize; ... };
然後,以類型參數
pM
MyStruct *
的位元組為單位的緩衝區大小會採用為:min(pM->nSize, sizeof(MyStruct))