我正在运行这个简单的程序,我得到的输出是“总线错误”。使用一些调试语句,我发现它发生的点是在strcat()调用。
#include<stdio.h>
#include<string.h>
main()
{
char *s = "this is ";
char *s1 = "me";
strcat(s,s1);
printf("%s",s);
return 0;
}
我在MAC,64位操作系统上使用gcc编译器运行它。如果我需要提供更多规格,请告诉我。
谢谢!
答案 0 :(得分:8)
"this is "
和"me"
是字符串文字,可能位于地址空间的只读部分。你不应该试图修改它们。
char s[] = "this is ";
char s1[] = "me";
这将确保将文字复制到堆栈 - 这是可写的。然后你的下面的strcat将溢出堆栈缓冲区,这同样糟糕。
以下内容可行 - 即使使用strcat
而非strncat
通常也是不良做法。
#include <stdio.h>
#include <string.h>
int main()
{
char s[100] = "this is ";
char *s1 = "me";
strcat(s,s1);
printf("%s",s);
return 0;
}
答案 1 :(得分:7)
一点背景:
表达式"this is "
和"me"
是字符串文字;它们分别是char
(C ++中的const char
)的9元素和3元素数组,具有静态范围(意味着它们的内存在程序启动时分配并保持到程序退出)。该内存可能是可写的,也可能不是可写的,具体取决于平台,因此尝试修改字符串文字会导致未定义的行为(意味着编译器可以逐字完成它想做的任何事情)。简而言之,您无法写入字符串文字。
当您编写strcat(s, s1);
时,您遇到两个问题:首先,目标数组是字符串文字,如上所述,它是不可写的。其次,它不足以容纳额外的角色;它的大小可以容纳9个字符(包括0个终结符),但是你试图存储11个字符。这是一个缓冲区溢出,如果你破坏了一些重要的东西,可能会导致糟糕的事情。
您必须分配可写的目标缓冲区。你有几个选择:
你可以声明一个足够大的数组来保存结果字符串,虽然一般你不会知道在编译时有多大“足够大”:
char *s = "this is ";
char *s1 = "me";
char target[11];
strcpy(target, s);
strcat(target, s1);
// alternately, sprintf(target, "%s%s", s, s1);
在C99中,您可以声明一个可变长度数组(VLA),其大小在运行时才知道:
char *s = "this is ";
char *s1 = "me";
char target[strlen(s) + strlen(s1) + 1];
strcpy(target, s);
strcat(target, s1);
// alternately, sprintf(target, "%s%s", s, s1);
您可以使用malloc
或calloc
动态分配目标缓冲区(这实际上是首选方法,因为缓冲区可以根据需要调整大小,与VLA不同):
char *s = "this is ";
char *s1 = "me";
char *target = malloc(strlen(s) + strlen(s1) + 1);
strcpy(target, s);
strcat(target, s1);
// or sprintf(target, "%s%s", s, s1);
...
free(target); // when you're finished with the buffer
答案 2 :(得分:2)
您需要详细了解字符串在C中的工作方式,以及字符数组和字符串文字之间的区别。
要使其工作,请重写它,例如如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char s[100] = "this is ";
char *s1 = "me";
strcat(s, s1);
printf("%s", s);
return EXIT_SUCCESS;
}
还有几点:
main()
返回int
。EXIT_SUCCESS
(来自<stdlib.h>
比0更清晰。)void
。对于main()
,空括号无效。