【问题标题】:How does a C/C++ compiler automatically deduce array length for certain C function calls? [duplicate]C/C++ 编译器如何自动推断某些 C 函数调用的数组长度? [复制]
【发布时间】:2012-11-30 14:30:21
【问题描述】:

可能重复:
How to find the sizeof(a pointer pointing to an array)

在第一次调用 strcpy_s 时,编译器可以推断出数组长度,但在第二次调用中,必须传入数组长度。

TCHAR szTemp[512];
::strcpy_s(szTemp, "a long text message");

TCHAR* pszTemp = new TCHAR[512];
::strcpy_s(pszTemp, 512, "a long text message");
delete []pszTemp;

编译器如何做到这一点?这是一个微软只有扩展吗?另外,如何声明我的方法以利用参数推导?

【问题讨论】:

  • @BoPersson:这个问题不是那个问题的重复,因为这个问题询问在某些情况下如何推断大小,而另一个问题没有。
  • @Eric - 这完全是关于数组和指针之间的区别。同样的问题。
  • @BoPersson:不,数组和指针之间的区别并不是“全部”。它询问关于推导大小的问题,并且在另一个问题中没有询问该问题,并且除了在排名第四的答案中没有讨论它,它没有解释它的示例。
  • 编译器不会推断数组的大小,它知道因为你告诉了它。该问题的更好措辞是类似于 函数如何知道数组的大小?

标签: c++ c visual-c++


【解决方案1】:

在第一次使用strcpy_s时,数组szTemp的元素个数是szTemp类型的一部分(因为它是“512个TCHAR的数组”),所以编译器知道关于它并可以完成声明strcpy_s的模板。

strcpy_s 的第二次使用中,pszTemp 是一个指针(它是一个“指向TCHAR”的指针),而不是一个数组,指向的元素个数不是类型的一部分。通常,编译器无法知道指针指向的位置有多少元素。 (在这种情况下,编译器可能会推断它,因为前面的代码显示了它,但这增加了编译器和通常被认为不值得实现的语言的复杂性。)

要自己执行此操作,请按照声明 strcpy_s 的方式声明模板:

template <size_t size> errno_t strcpy_s(
    char (&strDestination)[size],
    const char *strSource 
); 

这声明了一个基于参数size的模板,该模板用于一个函数,其第一个参数的类型为“引用charsize元素数组”。当编译器看到strcpy_s 的第一个参数是 char 的 512 个元素的数组时,它能够将此参数与模板中的参数相匹配,并推断出 size 是 512。

在其他地方,您将拥有模板的定义(不仅仅是声明)。该定义可以在其代码中使用模板参数size。当编译器看到strcpy_s 的使用时,它将在size 为512 的特化中实例化模板定义。

这仅适用于 C++,不适用于 C,因为 C 没有模板。

【讨论】:

  • 终于解释明白了,谢谢。
【解决方案2】:

根据docsstrcpy_s 作为具体函数存在,但也作为模板函数为已知大小的数组重载,例如您提供的szTemp 数组。在这种情况下,数组的大小就是函数定义的模板参数。

strcpy_s 本身是 Microsoft 独有的函数,因此模板版本并不比接受指针的版本更特定于 Microsoft。

【讨论】:

    【解决方案3】:

    第一个是使用模板,比如:

    template <size_t N>
    strcpy_s(char (&dest)[N], char const *source) { 
        // ...
    }
    

    在模板内部,N 是传递的数组的大小。

    在第二种情况下,pszTemp 是指针而不是数组,因此它不会与模板参数(需要实际数组)匹配,因此您需要显式传递目标大小。

    【讨论】:

      【解决方案4】:

      在第一种情况下,使用了模板函数(doc),所以没有魔法:

      template <size_t size>
      errno_t strcpy_s(
         char (&strDestination)[size],
         const char *strSource 
      ); // C++ only
      

      【讨论】:

        【解决方案5】:

        它可以推导出 szTemp 的数组长度,因为它被声明为一个数组。对于pszTemp,它被声明为一个指针,没有办法推断它的长度。

        据说有一些第三方 strcpy_s 实现,但主要是微软的事情——这是他们努力加强安全漏洞的一部分。

        【讨论】:

          猜你喜欢
          • 2011-02-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-17
          • 1970-01-01
          • 2015-03-13
          • 2020-01-21
          • 2011-05-23
          相关资源
          最近更新 更多