批註函式參數和傳回值

本文說明簡單函式參數的注釋一般用法,即純量,以及結構和類別的指標,以及大部分種類的緩衝區。 本文也會說明注釋的常見使用模式。 如需與函式相關的其他批註,請參閱 標注函式行為

指標參數

對於下表中的批註,當指標參數加上批註時,分析器會在指標為 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);
    

    在此範例中,呼叫端會為 提供 專案的 sizep1 緩衝區。 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)

    參數、欄位或結果介於 從 lowhi 的範圍(內含) 中。 相當於 _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; ... };

    然後,以類型參數 pMMyStruct * 的位元組為單位的緩衝區大小會採用為:

    min(pM->nSize, sizeof(MyStruct))

另請參閱