为什么这种MSVC API是这样定义的?

时间:2011-05-29 03:59:26

标签: c windows

errno_t _dupenv_s(
   char **buffer,
   size_t *sizeInBytes,
   const char *varname
);

我有几个问题:

  1. 为什么需要指向指针(**)的指针而不是指针(*)?
  2. 为什么sizeInBytes是必要的,strlen(buffer)
  3. 不可用。{

3 个答案:

答案 0 :(得分:4)

在msvc下以_s为后缀的任何函数都是一个安全函数,这意味着它不会对传递的数据的完整性做出任何假设。由于这个原因,字符串的长度是必需的,因为你不能假设它的空终止或终止(你可能只想要一半的字符串,但那是副作用)。

安全功能全部返回错误代码,以便可以检查它们而不会出现错误,因此需要通过指针发送任何返回。并将其视为strdup&的非安全版本dupenv返回char*,得到双重间接,以便指向您传递的变量的指针获取已分配缓冲区的地址。

答案 1 :(得分:0)

不,它要求字符指针的地址。该方法将分配必要的空间来保存变量的值并设置指向它的指针的值,否则为NULL。请参阅页面下方的示例代码:

http://msdn.microsoft.com/en-us/library/ms175774(v=VS.80).aspx

答案 2 :(得分:0)

在此上下文中,类型char**是指向char数组的指针。 (它也可以指向指向单个char的指针,但这不是它与_dupenv_s()一起使用的方式。)

_dupenv_s()函数通过要求操作系统保留一些足以容纳它的内存块来分配char数组。操作系统保留一块内存,并为_dupenv_s()函数提供此新分配的char数组的地址。 _dupenv_s()函数将此数组的地址存储到char*变量中,因为它是指向char s数组的指针。

现在,函数必须将此char*值传递给调用者,以便调用代码可以使用它。返回值已用于返回错误代码,因此无法使用。但是,让我们说调用者有一个char*变量准备好接收分配缓冲区的地址。

如果_dupenv_s()函数知道调用者的char*变量所在的位置,则该函数可以继续并使用正确的值填充调用者的char*变量。为此,调用者需要传递调用者的char*变量的地址。也就是说,您需要将指针传递给指向chars数组的指针。这意味着必须通过char**

请注意,这也是sizeInBytessize_t*的原因。调用者有一个变量size_t,调用者可以将变量的地址作为size_t*传递给函数,这样函数就可以用正确的值填充变量。

虽然strlen(buffer) == sizeInBytes可能属实,但strlen()函数通过计算字符数来确定字符串的长度,直到它看到空终止符。 strlen()完成所需的时间量与字符数成线性关系,即它不是常数。为什么不跳过要求调用者这样做并直接提供大小的麻烦?


如果指针仍然让您感到困惑(并且有时令人困惑),this Stack Overflow answer可能会有所帮助。