在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(代码= 2 ...)根据快速谷歌搜索,只是有内存分配错误的事情。
我认为你在两种情况下都为strA分配了相同数量的内存。有人可以赐教吗?
答案 0 :(得分:2)
在第一种情况下,您将strA
声明为char *
,指向包含字符串"Hello "
的静态内存。
在第二种情况下,您将创建一个包含6个字符的数组,并使用字符串"Hello "
进行初始化。
strcat
会尝试写入此静态内存段,从而立即导致错误。
第二个代码仍然无效(因为strA
不是一个足够大的数组来存储"Hello World"
),可能会也可能不会出现段错误,因为您没有尝试附加到字符串文字
答案 1 :(得分:0)
char * strcat ( char * destination, const char * source );
请参阅Here
该函数会将最终字符串写入第一个参数。在这种情况下,您无法将只读内存传递给它。
答案 2 :(得分:0)
这里实际上有很多事情发生。让我们逐一介绍。请考虑以下两个字符串“Hello”的声明。
char *strA = "Hello "; // #1
char strB[ 7 ] = "Hello "; // #2
第一个表达式是声明一个名为strA的字符指针,它指向内存的只读部分中的一个位置,其中“Hello”(或者是''h','e','l','l','存储o','','\ 0'})。第一个声明通常称为字符串文字。
第二个表达式是声明一个名为strB的字符数组,它由七个字符组成,并在堆栈中声明。重要的是要注意C中字符串的约定是在字符串末尾(一个字符数组)有一个 null终止符(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;
}
答案 3 :(得分:0)
我很惊讶第二个代码有效。为了使它在没有任何运行时错误的情况下工作,您可能希望使用动态内存分配。