2010-03-13 92 views
6

为什么此代码崩溃? 对字符指针是否使用strcat非法?为什么此代码崩溃?

#include <stdio.h> 
#include <string.h> 

int main() 
{ 
    char *s1 = "Hello, "; 
    char *s2 = "world!"; 
    char *s3 = strcat(s1, s2); 
    printf("%s",s3); 
    return 0; 
} 

请给出一个正确的方法来引用数组和指针。

+2

。它将第二个字符串附加到第一个字符串的末尾。它返回的字符串只是一个方便。你不能改变一个常量字符串(你的s1),这就是它崩溃的原因。 s1指向只读内存。 – 2010-03-13 05:08:22

+14

如果一切都很好,代码不会崩溃。 – 2010-03-13 05:08:35

+1

您可能想编辑您的问题,Ashish。你可能会因为你说“甚至一切都很好”而获得低价。不过,这是一个非常有效的问题。 – 2010-03-13 05:17:51

回答

11

问题是s1指向一个字符串字面值,并且您试图通过向其添加s2来修改它。您不允许修改字符串文字。您需要创建一个字符数组和字符串都复制到它,就像这样:

char *s1 = "Hello, "; 
char *s2 = "world!"; 

char s3[100] = ""; /* note that it must be large enough! */ 
strcat(s3, s1); 
strcat(s3, s2); 
printf("%s", s3); 

“足够大”是指至少strlen(s1) + strlen(s2) + 1+ 1是为了说明空终止符。

话虽如此,你应该认真考虑使用strncat(或者可以说是更好的,但是非标准strlcat,如果可用),这是边界检查,因而远远优于strcat

+0

可变长度数组(c99)或小于100的任何数值! :P – 2010-03-13 06:32:49

+0

是'strcat'返回第一个参数的原因是就像这样一个情况下,便利 - 这意味着你可以做一条线串联起来:'的strcat(strcat的(S3,S1),S2);' – caf 2010-03-13 07:49:51

+0

我实际上,在几乎所有这种情况下,实际上更喜欢snprintf到strncat。这是一个小小的性能问题,但由于strncat的正确用法与库的其余部分不一致,因此更有可能被正确使用。 ('n'的含义与人们想象的不同。) – 2010-03-13 08:17:15

2

在这种情况下,正确的方法是在目标字符串(s1)中分配足够的空间来存储6个额外字符(s2)以及该字符串的空终止符。

char s1[14] = "Hello, "; 
char *s2 = "world!"; 
char *s3 = strcat(s1, s2); 
printf("%s",s3); 
0

下面是从strcat的()手动报价道:“的strcat()函数将在src字符串到DEST串,覆盖在dest的端部的空字节(‘\ 0’),并然后添加一个终止的空字节,这些字符串可能不会重叠,并且dest字符串必须有足够的空间用于结果。“

这里的问题是,s1和s2指向“只读”的静态字符串,因此如果您尝试在dest参数中使用这样的字符串执行strcat操作,将会出现错误。

在这里创建你好世界字符串的最好方法是malloc它,因此它将能够包含s1和s2。另外,不要忘记在printf格式字符串的末尾添加'\ n',否则您可能会感到惊讶。

下面是代码,如果我是你,我会写:


int main() 
{ 
    char* s1 = "Hello "; 
    char* s2 = "World !"; 
    char *s3 = malloc((strlen(s1) + strlen(s2) + 1) * sizeof(char)); 
/* +1 is for the null terminating character 
and sizeof(*s3) is the actual size of a char. */ 

    if (s3) 
    { 
    strcat(s3, s1); 
    strcat(s3, s2); 
    printf("%s\n", s3); 
    free(s3); // always free what you alloc when you don't need it anymore. 
    } 
    return 0; 
} 
您正在使用的strcat错误