【问题标题】:char* passed into function is shortened to four characters [duplicate]传递给函数的char *缩短为四个字符[重复]
【发布时间】:2013-02-18 10:02:06
【问题描述】:
void myfunc(char* passedArray)
{
    cout << sizeof(passedArray) << endl; // prints 4
}

int main(void)
{
    char charArray[] = "abcdefghiklmop";

    cout << sizeof(charArray) << endl; // prints 15
    myfunc(charArray);
    cout << sizeof(charArray) << endl; // prints 15
}

我相信它仍然应该在该函数中打印 15...

【问题讨论】:

标签: c++ arrays parameter-passing sizeof


【解决方案1】:

这是指针和数组的经典问题。如您所见,问题在于数组衰减为指针。指针类型包含关于它所指向的数据的 no 元数据,但所指向的类型的大小除外。所有其他元数据,例如数组长度都会丢失。

因此,问题是您调用了myfunc,并带有一个指向数组的指针;然后,myfunc 函数将看不到有关数组的所有元数据。然后这会触发 sizeof 运算符的细微差别,即当它应用于指针时,它给出的是指针类型的大小,而不是数组的长度。但是,当应用于数组时,它会给出数组的长度,如您在 main 函数中所见。

短修复,改用strlen

【讨论】:

  • 所有这些都是对不同问题的一个很好的解释。他已经passedArray声明为一个指针,所以在他使用sizeof的时候没有衰减问题。并且解决方案不是使用strlen,而是使用std::string
  • 不,这是同一个问题,因为他在指针上调用sizeof,我只是想说明为什么会出现这个问题。我的“改用strlen”的解决方案只是来自我的纯C 背景,所以是的,std::string 是另一个有效的解决方案。他在调用函数时隐式将数组转换为指针时,仍然会出现衰减问题。
  • 没错。他在声明并定义为指针的对象上使用sizeofsizeof 周围没有衰减问题。 (如果他问他如何将数组传递给声明为采用指针的函数,或者如果他声明 myfunc 采用数组,那么您的答案将是合适的。)
  • @JamesKanze 够公平的,我同意你的观点。我经常看到这一点,尽管当人们学习 C 时,他们希望 sizeof 是一个运行时函数,它给出了他们扔给它的任何东西的大小,包括数组的长度。通常,这是因为他们没有正确意识到指针和数组之间的实际差异。我只是试图给出一个解释,表明他将所述数组作为指针传递,这样做的效果同时还试图阐明 sizeof(ptr) 返回指针的大小,而不是他预期的数组。跨度>
  • 我也很欣赏当你查看代码时这看起来很明显,但是新程序员确实最终会被锁定在一个循环中在数组上调用时,数组将与预期完全相同。有时它只是为了“哦……是的”而额外踢球。时刻。
【解决方案2】:

首先,您期望什么?您已将 passedArray 定义为 一个指针,所以sizeof(passedArray) 将返回大小 机器上的指针。它还能做什么?我可以 如果您的功能是:

void myFunc( char passedArray[15] )

一个理性的人可能会认为sizeof(passedArray) 是 15 在这种情况下(但他错了,因为当用作 一个参数,数组被编译器转换成 一个指针,这个定义和你的完全一样)。

这一切的答案是使用std::string

void
myFunc( std::string const& passedValue )
{
    std::cout << passedValue.size() << std::endl;
}

char[] 不同,std::string 确实有效。 C 风格的数组, 无论是否用作字符串,都已损坏,并且只能 在非常有限的情况下使用,主要与对象有关 具有静态生命周期和初始化顺序问题。

【讨论】:

  • 对 C/++ 来说相对较新,没有理由期望它会被转换为指针。我正在调试一段在期望数组的指针上使用 sizeof() 的旧代码。
  • @NicholasPickering 该函数定义了myFunc( char* )char* 是一个指针。时期。 myFunc 中没有隐式转换或任何内容。 (当然,在调用站点有一个隐式转换。但这是一个不同的问题。)不管你对 C++ 有多陌生(没有 C/C++ 这样的东西),如果你定义了一个类型 X,为什么你会期待一个类型Y。 (事实上​​,正如我所指出的,有一种这样的情况。但它不会出现在你的程序中。)
  • 我是在暗示我对这两者都是新手,而不是程序同时使用两者。我希望这可能是因为我真的只有弱类型语言的经验。
【解决方案3】:

虽然您将数组定义为char charArray[],但当您将其传递给采用char* 的函数时,charArray 将被转换为指向第一个元素的指针,因此当您在函数体,它会按预期打印指针的大小(在 32 位机器上为 4 个字节)。

Even if your function took char passedArray[] as an argument,原来的charArray 将衰减为指向第一个元素的指针,并且通过调用sizeof 检索此数组大小的能力将丢失。 (见What is array decaying?)。

因此您可以调用strlen() 来检索此 C 样式字符串的大小,但由于您正在编写 C++ 代码,因此最合理的解决方案是使用 std::string 而不是 C 样式字符串。

【讨论】:

  • +1 表示“数组衰减”链接
【解决方案4】:

使用strlen(),而不是sizeof(),来获取字符串的长度。

在 C 中,字符串只是一个以零结尾的字符数组。 C 中没有特殊的 String 类型。strlen() 是一个计算字符数直到终止零字节的函数。

sizeof() 是一个运算符,可用于确定变量或数据类型的大小。在您的情况下,sizeof() 返回 char* 指针的大小(在您的平台上似乎是 4 个字节)。

【讨论】:

  • 那么 sizeof() 是做什么的?为什么它在 main 内部和函数内部有所不同?
  • @NicholasPickering sizeof 返回作为其参数的对象的大小。你的参数类型为char*,因此它返回char* 的大小。它在 main 中给出了不同的结果,因为您已将其应用于不同的对象。
  • 他标记了 C++ 的发布,并且使用了std::cout,所以 C 所做的或多或少无关紧要。在 C++ 中,字符串是在标准库中定义的类类型,在您成为专家之前,您应该使用它。
  • 此代码已过时。我正在调试它。最初的开发者使用了sizeof,而他应该使用你们都建议的任何其他代码。
【解决方案5】:

sizeof(char*) 给出指针的大小,而不是指向字符串的大小。

你真正想要的是strlen

它在main() 中给出字符串大小的原因是因为它被定义为char[](一个在编译时知道大小的数组)而不是char*

【讨论】:

  • 他真正想要的是std::string,而不是strlen
【解决方案6】:

在函数内部,this

cout << sizeof(passedArray) << endl;

正在打印passedArray 的大小,即achar*。在您的平台上,指针大小为 4。如果将指针传递给函数,则该函数无法知道它指向的是固定大小数组的第一个元素。如果你想要一个固定数组的大小,那么传递一个数组,而不是一个指针:

template< class T, size_t N >
void myfunc( const T (&passedArray)[N] )
{
  std::cout << N << "\n";
}

【讨论】:

    【解决方案7】:

    sizeof(passedArray) 返回指针 passedArray 的大小,它的类型为 char *,在您的系统中,显然是 4 个字节。

    改用strlen,或者更确切地说,使用std::string

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多