【问题标题】:size of string array through function通过函数的字符串数组的大小
【发布时间】:2013-03-06 20:03:40
【问题描述】:

如何找到传递给函数的字符串数组的大小。大小应在函数内部计算。

#include<iostream>

using namespace std;


template <typename T,unsigned S>
unsigned arraysize(const T (&v)[S]) { return S; }

void func(string args[])
{
   unsigned m=arraysize(args);
   cout<<m;
}

int main()
{
    string str_arr[]={"hello","foo","bar"};

    func(str_arr);  
}

我不明白的是:

如果在main中使用arraysize(str_arr)这个语句,不会有问题。 str_arr 是一个数组,所以 str_arr 充当一个指针,所以当我们使用 arraysize(str_arr) 时,这意味着我们正在将地址发送给 arraysize 函数。(如果我错了,请纠正我)。

但在函数func()中,我不明白为什么会出现问题,即语句arraysize(args)发送字符串数组args的地址(或指针args的地址)..还是更复杂,因为它变成一些双指针??解释一下?

另外请更正上面的代码..

【问题讨论】:

  • 无法确定数组大小和指针大小。并非没有专用的终止字节。这就是我们从 argc 开始的原因。
  • 另一个使用std::vector的理由。
  • 这是 java 数组相对于 c++ 指针的优势之一,数组的大小可从数组本身获得。 Dmitry 是正确的,在 C++ 中,您要求的内容是不可能的。
  • @Dmitry 确定数组大小很容易(它在类型中,所以sizeof 可以使用它),前提是您确实有一个数组,而不是指向数组第一个元素的指针; -)
  • @Dmitry 说到混淆,我在你的定义中也看到了很多混淆 ;-) char 确实是一个字节,因为它是 C-the- 的最小可寻址内存单元语言,但它不是所有平台上的八位字节(8 位)。 int 没有被定义为双字,除非可能被某些 ABI 定义(当您希望您的软件在多个单一平台上运行时,这确实不值得)。 Unicode 字符在任何意义上都不是 16 位 - UTF-16 代码单元,但这很少有用或重要(还有其他更好的编码;并非所有 代码点 i> 适合 16 位)。

标签: c++ arrays function parameters size


【解决方案1】:

str_arr 是一个字符串数组。当您执行sizeof(str_arr) 时,您将获得该数组的大小。然而,尽管args 看起来像一个字符串数组,但事实并非如此。看起来像数组的参数实际上是指针类型。也就是说,string args[] 被编译器转换为string* args。当您执行 sizeof(args) 时,您只是获取指针的大小。

您可以将数组的大小传递给函数,也可以使用模板参数大小获取对数组的引用(就像您对 arraysize 所做的那样):

template <size_t N>
void func(string (&args)[N])
{
   // ...
}

【讨论】:

  • 哈哈......这就是我的想法......它被转换成字符串*。
【解决方案2】:

当发送到函数时,无法确定数组的大小。您还必须记住,只有一个指向数组的指针被发送给函数,这使得计算数组的大小在理论上甚至非常不可信。

【讨论】:

    【解决方案3】:

    数组大小的信息在您的函数中永远不可见,因为当您决定使用 string args[] 作为参数时,您将其丢弃了。从编译器的角度来看,它与string* args 相同。您可以将函数更改为:

    template<size_t M>
    void func(string (&args)[M])
    {
       cout<<M;
    }
    

    但你似乎已经知道了,对吧?

    【讨论】:

    • no :) 但是谢谢 :)... 还是需要掌握这种模板用法!
    【解决方案4】:

    如果在main中使用arraysize(str_arr)语句,它不会构成一个 问题。 str_arr 是一个数组,所以 str_arr 充当指针,所以 当我们使用arraysize(str_arr) 时,这意味着我们将地址发送到 arraysize 函数。(如果我错了,请纠正我)。

    我必须在这里纠正你。你陈述了一个正确的前提,却得出了错误的结论。

    关键是str_arr确实是main中的一个数组。虽然数组在许多(大多数)表达式上下文中衰减为指针,但当对数组的引用被初始化时,这并不适用。这就是为什么 array_size 被声明为引用数组参数的原因 - 这是拥有数组类型参数的唯一方法,这意味着它具有定义的长度。

    func 并非如此。当函数参数被声明为普通数组类型时,指向指针衰减的数组将应用于该声明。您对func 的声明等同于void func(string * args)。因此args 是一个指针,而不是一个数组。你可以打电话给func

    string str_non_array;
    func(&str_non_array);
    

    因此,数组引用不能绑定到它。无论如何,args 已经完全丢失了有关它指向的数组大小的所有信息。

    您可以使用与arraysize 中使用的相同的数组引用技巧:将func 声明为

    template <std::size_t N>
    void func(string (&args)[N]);
    

    但这在任何地方都是不切实际的(如果天真地应用于所有数组处理代码,可能会导致代码膨胀)。在其他语言中可用的 C++ 等价数组是 std::vector&lt;string&gt;(对于动态大小的数组)或 std::array&lt;string,N&gt;(对于在编译时已知的固定大小)。请注意,后者可能会导致与上述相同的代码膨胀,因此在大多数情况下,std::vector&lt;string&gt; 将是您需要传递给各种函数的数组的首选类型。

    【讨论】:

    • std::array&lt;T,N&gt; 导致的代码膨胀与 functemplate&lt;std::size_t N&gt; 的版本一样多。
    • 如您所说,对数组的引用已初始化,为什么 str_arr 被初始化为引用但不转换为指针?抱歉,如果这不是一个有效的问题?基本上我要问的是为什么 str_arr 在我的代码上下文中没有被用作指针。
    • @bkunchanapalli: str_arr in main 一个数组。它在需要数组的上下文中用作数组,但在需要指针的上下文中衰减为指针。在您对func(您的版本)的调用中,参数类型为string *,因此str_arr 用作(衰减为)指针。如果您将在main 中使用arraysize(str_arr),则参数类型为数组引用,并且该引用v 将直接绑定到str_arr没有 数组到指针的转换。在func 中这是不可能的,因为args 是一个指针而不是一个数组。
    【解决方案5】:

    Dmitry 是对的,我想进一步解释一下。它发生的原因是因为数组不是 C++ 中的 First Class citizen,当作为参数传递时,它会衰减为指针,而你在被调用函数中得到的是指向其第一个元素的指针,并且大小丢失了。 您可以参考C++ arrays as function arguments 了解有哪些可用的替代选项。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-02
      • 1970-01-01
      • 1970-01-01
      • 2022-06-13
      • 1970-01-01
      • 1970-01-01
      • 2021-11-10
      • 2020-10-18
      相关资源
      最近更新 更多