C数组不能正常工作

时间:2012-02-01 17:13:51

标签: c

所以我的main方法中有一个C字符串(字符数组),当我将它作为参数传递给另一个方法时,它的大小会发生变化。

void method(char* arr){
    printf( "%u\n", sizeof(arr) ); //returns 4, in my program.
    arr = "hello "; //executes just fine
    char arr2[9] = "people";
    strcat(arr, arr2); // (1) here is where it crashes down
    int i = 0; while(i < sizeof(arr2)){ arr[i+6] = arr2[i]; i++;} // (2) this causes it to crashdown too
}

int main(){
    char array[33];
    printf("%u\n", sizeof(array) ); //returns 33, in my program.
    method(array);
}

为什么会这样?,我该如何解决?这是否意味着我无法为C字符串添加更多值?我怀疑这可能是我的程序不断崩溃的原因(每当我尝试添加n时)。 标记为(1)和(2)的行也不起作用。有解决方法吗?

6 个答案:

答案 0 :(得分:8)

以下是发生的事情:

  1. main()中,您将sizeof()应用于数组,因此您可以获得数组的大小。

  2. main()调用method()时,数组decays成为指针(因为method()需要指针)。

  3. method()中,您将sizeof()应用于指针,因此您可以获得指针的大小。

  4. 要修复,请将arr的实际分配大小作为附加参数传递给method(),并使用该参数作为对允许写入{{1}的内容的限制}。

    作为旁注,以下内容并不符合您的预期:

    arr

    这不会修改底层数组;它只是将arr = "hello "; //executes just fine 重新指向字符串文字。您应该使用arr而不是作业。

答案 1 :(得分:2)

自然地,

cout << sizeof(arr) << endl; //returns 4, in my program.

打印4,因为这里实际上是打印sizeof(char*),即指针的大小,而在main()函数中你正在打sizeof(sizeof(char) * 33)

如何修复:好吧,问题是你的功能签名:

void method(char* arr)

使用接收指向数组指针的函数需要在函数签名中添加一个参数来指定数组的大小:

void method(char* arr, int arr_size)

这是唯一的方法。

答案 2 :(得分:2)

  1. 你在指针上做sizeof,而不在数组上。 无法按值将数组传递给函数。你不能。

  2. 然后用一个指向"hello"的新副本替换所述指针的本地副本。然后期望能够获得字符串"hello"的第8个字符显然不起作用。

    • 您使用的是C ++。使用std::stringstd::vector

答案 3 :(得分:0)

如果您想知道函数的大小,有3种方法:

  • 将char数组的长度作为第二个参数传递。
  • 在方法中使用strlen函数
  • 将方法签名更改为void method(const std::string& arr);,您将能够使用arr.size();来获取字符串的大小。如果您使用C ++编写,更安全的方法是使用std::string而不是char*

答案 4 :(得分:0)

由于您正在编写C ++(即使它是像那样的批次),更改“方法”(名称的选择不当,如果我可以这样说)到 -

void method(char (&arr)[33]) // I would recommend std::string instead
{
    cout << sizeof(arr) << endl; // should return 33 in your program.
    strcpy(arr, "hello "); // should execute per behaviour defined by ISO
    char arr2[] = "people"; // Note that arr2 is followed by '[' and an immediate ']'
    strcat(arr, arr2); // Now this should work, although std::string is still better.
}

请注意,即使这就像C(因为它使用的是vanilla字符数组而不是std :: string)。

答案 5 :(得分:0)

C中的“正确”代码。

int method(char* arr, size_t size, bool useStrcat)
{
   const char * prefix = "hello "; // could be static
   size_t prefixLen = strlen( prefix ); // which will be 6. Could be static.
   strncpy( arr, "hello ", size );
   char arr2[] = "people";     
   if( useStrcat )
   {
       strncat(arr, arr2, size - prefixLen);  
   }
   else
   {
       for( int i = 0; i < sizeof(arr2) && i < (size - prefixLen); ++i )
       {
          arr[i+prefixLen] = arr2[i];
       }
   }
   return prefixLen + sizeof(arr2);
}
  1. 传递缓冲区的大小。
  2. 即使它不够大,这个功能也不会溢出它。
  3. 当strncat路径溢出缓冲区时,它在逻辑上是不同的。这将保留空终止符的最后一个字符,但for循环不会,并且将使您的字符串不以空值终止。当然,修复方法是将(size - prefixLen - 1)放入for循环中,然后强制使用null终止符。
  4. 请注意,arr2将其null终结符作为其大小的一部分,因此当缓冲区未达到容量时将写入它。

    执行此操作的许多程序将为您返回他们想要写入的字符数,并且通常会被调用两次,第二次使用足够大的缓冲区,有时第一次调用是故意使用0大小的缓冲区只是为了获得计数。

    通过传递来测试从main调用的此方法: - useStrcat的值不同 - 缓冲区大小小于输出所需的缓冲区大小(在本例中为13)。

    请注意打印未终止的字符串。无论如何,你的“主”总是可以分配13并将其置于空本身,例如

    int main()
    {
       char buf[13] = {0};
       method( buf, 12, false ); // do not use strcat
       puts( buf );
    }