我在c中学习编程,而且我遇到了一些奇怪的事情。
我正在使用char数组/字符串并使用不同的函数。所以我有这个程序,
#include <stdio.h>
int main(){
char a[] = {'H','e','y','a','\0'};
strcat(a,"bro!");
printf(a);
}
$ gcc -o test.o test.c -Wall
$ ./test.o
Heya bro!
$
按预期工作,但如果我添加
#include <string.h>
到开头,然后我得到了这个
$ gcc -o test.o test.c -Wall
$ ./test.o
Abort: trap 6
$
答案 0 :(得分:3)
strcat
尝试附加字符,但是数组的大小又不足以让它们给你undefined behavior。(在这种情况下,未定义的行为导致你看到的错误 - 它可能是一切都有效的情况。)因为strcat
试图超越数组a
。 printf
的第一个参数应该是格式说明符,如printf("%s",a);
。
char a[] = {'H','e','y','a','\0'};
此处a
有5个元素。数组的大小为5
。你需要采取更大的阵列。
char a[9] = {'H','e','y','a','\0'};
如果你让数组保持9个字符,那就可以了。
答案 1 :(得分:3)
初始化数组并省略维度时,编译器会根据初始化程序的数量推断维度 所以,这句话:
char a[] = {'H','e','y','a','\0'};
相当于:
char a[5] = {'H','e','y','a','\0'};
strcat()
将源字符串的副本附加到目标字符串。它不检查目标缓冲区是否足够大以包含连接的结果字符串。如果目标不足以容纳连接的结果字符串,那么它会导致未定义的行为,包括它可能执行不正确(崩溃或静默生成不正确的结果),或者它可能完全符合程序员的意图。
您应该指定缓冲区a
的大小足以容纳连接的结果字符串。在您的计划中,源字符串bro!
的大小为4
。 strcat()
使用源字符串的第一个字符覆盖目标null
字符,同时连接它们,并且在形成的新字符串的末尾包含空字符。因此,在您的情况下,保持连接结果字符串所需的最小大小为9
。
将a
声明为:
char a[9] = {'H','e','y','a','\0'};
应该可以正常工作。
正如David建议(在评论中)而不是9
,您可以采用一些合理大小的缓冲区,例如512
或1024
(例如a[512]
或{{1 }})。
它可以帮助您在一定程度上避免问题。但是,您需要处理代码中的缓冲区溢出问题。例如,您可以使用strncat(),这样您就可以灵活地指定可以在目标字符串中追加的最大尺寸。
您可以指定要附加的最大字符数 -
a[1024]
以避免缓冲区溢出。