问题描述
这个程序假设打印 Hello World 但猜猜退出的是什么,为什么会发生分段错误?
#include <stdio.h>
#include <string.h>
char f(char *a,char *b)
{
int i,m,n;
m = strlen(a);
n = strlen(b);
for (i = 0; i<=n; i++)
{
a[m+i] = b[i];
}
}
int main() {
char*str1 = "hello ";
char*str2 = "world!";
str1=f(str1,str2);
printf("%s",str1);
return 0;
}
解决方法
您不能修改字符串文字。使用具有足够元素的数组来代替要修改的字符串。
同时将 f
的返回值分配给 str1
是一个坏主意,因为在函数 return
中没有执行 f
语句并且使用其返回值调用 未定义的行为。如果您不打算返回任何内容,则应将返回类型更改为 void
。
#include <stdio.h>
#include <string.h>
void f(char *a,char *b)
{
int i,m,n;
m = strlen(a);
n = strlen(b);
for (i = 0; i<=n; i++)
{
a[m+i] = b[i];
}
}
int main() {
char str1[16] = "hello ";
char*str2 = "world!";
f(str1,str2);
printf("%s",str1);
return 0;
}
,
一个一个地复制字符重要吗? 因为如果不是,您可以像这样将一个字符串复制到另一个字符串。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
char str1[] = "hello ";
char str2[] = "world!";
char *result = malloc(strlen(str1) + strlen(str2) + 1);
strcpy(result,str1);
strcat(result,str2);
printf("%s",result);
return 0;
}
,
首先,这个:
char*str1 = "hello ";
是一个指向常量数据的指针,这意味着你不能改变字符串"hello "
这是一个指向可变数据的常量指针:
char str1[] = "hello ";
这意味着 str1
始终指向内存中的相同地址,但您可以修改该内存块的内容。
然而,str1
将有 7 个字符的固定大小(不要忘记计算 \0
),因此您不能向其附加另一个字符串。
您可以定义一个足够大的 #define SIZE 20
大小来存储两个字符串并声明
char str1[SIZE] = "hello ";
或者您可以在声明要追加的字符串后将 str1
声明为 VLA(可变长度数组):
char*str2 = "world!";
char str1[strlen("hello ")+strlen(str2)+1] = "hello ";
其中 +1
代表 \0
。
对于初学者,您不能更改字符串文字(在这种情况下,指针 str1
指向的字符串文字)。
char*str1 = "hello ";
char*str2 = "world!";
任何更改字符串文字的尝试都会导致未定义的行为。
您需要分配一个足够大的字符数组来存储带有指针 str2
指向的附加字符串文字的结果字符串。
其次,已经存在执行所需任务的标准 C 函数 strcat
。如果您必须自己编写这样的函数,那么您似乎不应该使用任何字符串函数,例如 strlen
。
而且你的函数的返回类型 char 没有意义。而且实际上你的函数什么都不返回。
所以这个任务
str1=f(str1,str2);
导致未定义的行为。
该函数和整个程序可以在不使用标准字符串函数的情况下按以下方式编写。
#include <stdio.h>
char * f( char *s1,const char *s2 )
{
char *p = s1;
while ( *p ) ++p;
while ( ( *p++ = *s2++ ) );
return s1;
}
int main(void)
{
char s1[14] = "Hello ";
char *s2 = "World!";
puts( f( s1,s2 ) );
return 0;
}
程序输出为
Hello World!
注意第二个函数参数应该有限定符const
,因为指向的字符串在函数内没有改变。并且函数返回类型应该是char *
,即函数应该返回结果字符串。
首先,您不能更改常量字符串,这是未定义的行为。
其次,您的 f
函数没有 return 语句,因此返回随机数据,使 str1
中的 main
变量指向随机内存。使用它也有未定义的行为。
要修复它,您应该分配新的内存并将字符串连接到其中
char* f(const char *s1,const char *s2)
{
char *s = malloc(strlen(s1) + strlen(s2) +1);
if (s) {
strcpy(s,s1);
strcat(s,s2);
}
return s;
}
额外分配的一个字节用于终止零。
两个参数都是 const
因为没有理由修改它们,这允许两个参数都是文字字符串。