我是C语言的新手。我试图使用strcat函数。
#include <stdio.h>
#include <string.h>
int main(int argc, const char *argv[]) {
char s1[] = "12345";
char s2[] = "abcde";
strcat(s1, s2);
puts(s1);
puts(s2);
return 0;
}
这个正常运行,但是
#include <stdio.h>
#include <string.h>
int main(int argc, const char *argv[]) {
char* s1 = "12345";
char* s2 = "abcde";
strcat(s1, s2);
puts(s1);
puts(s2);
return 0;
}
最后一个未能返回结果。为什么两种不同的声明方式在strcat函数中返回不同的结果。提前谢谢。
答案 0 :(得分:8)
两个代码段都会调用未定义的行为。在第一个代码段s1
中没有足够的空间来容纳除六个字符之外的任何其他字符
在第二个片段中,您尝试修改字符串文字。任何修改字符串文字的尝试都会导致未定义的行为。
[...]字符串可能不重叠,
dest
字符串必须有足够的空间用于结果。如果dest
不够大,程序行为是不可预测的;缓冲区溢出是攻击安全程序的最佳途径。
答案 1 :(得分:6)
在C中,函数strcat
不会创建包含连接字符串的新字符数组。它将第二个字符串中的字符附加到第一个字符数组的第一个字符串,前提是它有足够的元素来存储新字符。否则,该函数将尝试覆盖导致未定义行为的字符数组之外的内存。
因此,在第一个程序中有效使用该函数可以采用以下方式
#include <stdio.h>
#include <string.h>
int main(int argc, const char *argv[]) {
char s1[11] = "12345";
char s2[] = "abcde";
strcat(s1, s2);
puts(s1);
puts(s2);
return 0;
}
在这个程序中,字符数组被声明为有11个元素。因此,它能够容纳附加的字符串"abcde"
。
在第二个程序中,尝试修改指针s1
指向的字符串文字。 C和C ++中的字符串文字是不可变的。任何更改字符串文字的尝试都会导致未定义的行为,即使在与C ++字符串文字相反的C中也有非常量字符数组的类型。
来自C标准(6.4.5字符串文字)
7未指明这些阵列是否与它们不同 元素具有适当的值。 如果程序尝试 修改这样的数组,行为是未定义的。
因此,在第二个程序中,您再次需要使用具有足够元素的字符数组。例如
#include <stdio.h>
#include <string.h>
int main(int argc, const char *argv[]) {
char s1[11] = "12345";
char* s2 = "abcde";
strcat(s1, s2);
puts(s1);
puts(s2);
return 0;
}
或者,如果编译器支持可变长度数组(VLA)或动态分配数组,则可以使用它。例如
#include <stdio.h>
#include <string.h>
int main(int argc, const char *argv[]) {
char *s1 = "12345";
char* s2 = "abcde";
char s3[strlen( s1 ) + strlen( s2 ) + 1];
strcpy( s3, s1 );
strcat( s3, s2 );
puts(s1);
puts(s2);
puts(s3);
return 0;
}
或者
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[]) {
char *s1 = "12345";
char* s2 = "abcde";
char *s3 = malloc( strlen( s1 ) + strlen( s2 ) + 1 );
if ( s3 != NULL )
{
strcpy( s3, s1 );
strcat( s3, s2 );
puts(s1);
puts(s2);
puts(s3);
}
free( s3 );
return 0;
}