2

在 C 中,为什么这不起作用:

#include <stdio.h>
int main(void)
{
    char * strA = "Hello ";
    strcat(strA, "World!");
    printf("%s", strA);
    return 0;
}

但这确实:

#include <stdio.h>
int main(void)
{
    char strA[6] = "Hello ";
    strcat(strA, "World!");
    printf("%s", strA);
    return 0;
}

我会提出错误,但可惜我使用的是 Xcode,它不喜欢在失败时给我任何可用的东西,只是给我 BAD_ACCESS_EXC(code =2...) 根据快速谷歌搜索,只是有与内存分配错误有关。

我认为您在两种情况下都为 strA 分配了相同数量的内存。有人可以启发我吗?

4

4 回答 4

2

在第一种情况下,您声明strAchar *,指向包含字符串的静态内存"Hello "

在第二种情况下,您正在创建一个由 6 个字符组成的数组,用 string 初始化"Hello "

strcat因此,在第一种情况下,尝试写入此静态内存段,立即导致错误。

第二个代码仍然无效(因为strA没有足够大的数组来存储"Hello World"),可能会或可能不会出现段错误,因为您没有尝试附加到字符串文字。

于 2013-08-08T23:30:46.840 回答
0

我很惊讶第二个代码有效。为了让它在没有任何运行时错误的情况下工作,您可能需要使用动态内存分配。

于 2013-08-09T06:16:45.157 回答
0

这里实际上发生了很多事情。让我们一步一步来。考虑以下两个字符串“Hello”的声明。

char *strA = "Hello "; // #1
char strB[ 7 ] = "Hello "; // #2

第一个表达式是声明一个名为 strA 的字符指针,它指向内存的只读部分中“Hello”(或者 { 'h', 'e', 'l', 'l', 'o', ' ', '\0' }) 被存储。第一个声明通常称为字符串文字

第二个表达式是声明一个名为 strB 的字符数组,它由七个字符组成,并在堆栈上声明。重要的是要注意,C 中字符串的约定是在字符串(字符数组)的末尾有一个空终止符(0 字符)——你错过了这个。初始化语法(双引号)自动用 0 填充尾随条目,无论它在哪里声明。

现在,直接回答你的问题。您不能覆盖只读内存,因此如果您尝试修改 strA 指向的任何内存(字符串文字),则会导致错误。您可以修改 strB 指向的内存块,但是您需要初始化一个更大的数组以正确容纳字符 'w'、'o'、'r'、'l'、'd' 和 '!'。编译器将允许您写入您无权访问的内存,但不能保证它不会分配给同一堆栈帧或另一个程序上的其他变量。

这将是正确的代码片段:

#include <stdio.h>

int main( void ) {
  // Declares an array of characters, strA with a length of 13.
  char strA[ 13 ] = "Hello ";

  // Concatenates the characters 'w', 'o', 'l', 'r', 'd' and '!' to strA.
  strcat( strA, "World!" );

  // Outputs to stdout.
  printf( "%s", strA ); // => "Hello World!"

  return 0;
}
于 2013-08-09T04:41:38.103 回答
0
char * strcat ( char * destination, const char * source );

这里

该函数会将最终字符串写入第一个参数。在这种情况下,您不能将只读内存传递给它。

于 2013-08-09T00:26:09.277 回答