简体   繁体   English

WinAPI令人困惑的函数参数

[英]WinAPI confusing function parameters

The API reference for the function in question: RmStartSession . 有关功能的API参考: RmStartSession

The code: 编码:

#include <Windows.h>
#include <RestartManager.h>

/*
DWORD WINAPI
RmStartSession(
    _Out_ DWORD *pSessionHandle,
    _Reserved_ DWORD dwSessionFlags,
    _Out_writes_(CCH_RM_SESSION_KEY + 1) WCHAR strSessionKey[]);
*/

int main(int /*argc*/, char** /*argv*/)
{
    WCHAR sessionKey[CCH_RM_SESSION_KEY + 1];

    // 1.
    DWORD *sessionOne = nullptr;
    auto returnCodeOne = RmStartSession(sessionOne, NULL, sessionKey); // = 160 ERROR_BAD_ARGUMENTS

    // 2.
    DWORD sessionTwo = 0xFFFFFFF;
    DWORD *pSessionHandleTwo = &sessionTwo;
    auto returnCodeTwo = RmStartSession(pSessionHandleTwo, NULL, sessionKey); // = 0 ERROR_SUCCESS

    // 3.
    DWORD sessionThree = 0xFFFFFFF;
    auto returnCodeThree = RmStartSession(&sessionThree, NULL, sessionKey); // = 0 ERROR_SUCCESS

    return 0;
}  

Took me a while to realize why 1. was giving me a BAD_ARGUMENTS error, since all of the variations above compiled fine and were legit language constructs. 花了我一段时间才意识到为什么1.给我一个BAD_ARGUMENTS错误,因为上述所有变体都可以很好地编译并且是合法的语言构造。

The problem is that the function actually needs a pointer to a valid object and just uses that pointer to modify the object, does not modify the pointer itself. 问题在于该函数实际上需要一个指向有效对象的指针,而只是使用该指针来修改该对象,而不会修改指针本身。 So if the pointer is nullptr then there's no object to modify, the function does not allocate an object itself. 因此,如果指针为nullptr则没有要修改的对象,该函数本身不会分配对象。
(Please correct me if my understanding above is wrong) (如果我的理解有误,请纠正我)

That being said, why wasn't the function defined to request a reference to a DWORD to make it clear that it cannot be null, is there a specific reason to use a pointer here? 话虽这么说,为什么没有定义函数来请求对DWORD的引用以明确表明它不能为null,在这里是否有特定的原因使用指针?
What am I missing? 我想念什么?

There are two answers to this question: 这个问题有两个答案:

  1. This is a C api, so references were not available to the API writers. 这是C api,因此API编写者无法使用参考。

  2. There is a school of thoughts that using references for output value parameters is bad API design, and pointers should always be used, even if it means that passing a nullptr would be a disaster. 有一种流派认为,对输出值参数使用引用是不好的API设计,并且应该始终使用指针,即使这意味着传递nullptr将会是一场灾难。

The idea is that reference-based output parameters are really confusing at the call site. 这个想法是,基于引用的输出参数在呼叫站点上确实令人困惑。 Look at the following code: 看下面的代码:

void foo() {
   my_struct val;
   bar(val);
}

void foo_alt() {
   my_struct val;
   bar_alt(&val);
}

At first glance, one would not expect bar to modify val in the first example, but one would suspect it in the second. 乍一看,在第一个示例中,不要指望bar修改val ,但是在第二个示例中,可能会怀疑它。

Understanding what a function does by only looking at the call site is fundamental to self-documenting code, and mutable references often break that (unless it's really clear in the function name). 仅通过查看调用站点来了解函数的功能是自我记录代码的基础,并且可变引用通常会破坏这一点(除非函数名称中确实很清楚)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM