C 手动编码串联功能错误(分段故障(堆芯转储))

C 手动编码串联功能错误(分段故障(堆芯转储)),c,C,我试图创建一个函数,将a、b和c串联在一个名为result的变量中 #包括 常量char*concat(char*a,char*b,char*c){ char*result;//串联变量(A+B) int i;//A、B和C的索引 int ir;//结果的索引 //结果=A 对于(i=0;a[i]!='\0';i++){ ir=i; 结果[ir]=a[i]; } // → 对于 //结果=A+B ir++; 对于(i=0;b[i]!='\0';i++){ 如果(i==0) ir=ir+i; 结果

我试图创建一个函数,将
a
b
c
串联在一个名为
result
的变量中

#包括
常量char*concat(char*a,char*b,char*c){
char*result;//串联变量(A+B)
int i;//A、B和C的索引
int ir;//结果的索引
//结果=A
对于(i=0;a[i]!='\0';i++){
ir=i;
结果[ir]=a[i];
} // → 对于
//结果=A+B
ir++;
对于(i=0;b[i]!='\0';i++){
如果(i==0)
ir=ir+i;
结果[ir]=b[i];
} // → 对于
//结果=A+B+C
ir++;
对于(i=0;c[i]!='\0';i++){
ir=ir+i;
结果[ir]=c[i];
} // → 对于
返回结果;
} // → 连接()
但当我编译并运行以下块时,它会导致
分段错误(内核转储)
错误。我已经搜索过了()但是没有发现。我做错了什么

intmain(){
char*a=“1234567”;
char*b=“abcdefg”;
char*c=“\uuuuuuuuuuuuuuuuuuuuu”;
printf(“%s”,concat(a,b,c));
}
错误:

分段故障(堆芯转储)

您永远不会初始化
结果,因此它将有一个随机值,因此您得到了UB(未定义的行为),这可能会导致segfault

您必须对
结果执行
malloc
。而且,它需要有足够的空间来容纳所有连接字符串的长度

这里有一些更新的代码。请注意,我没有彻底检查您的
循环,但乍一看,它们似乎没有问题

但是,您必须在
result
的末尾添加EOS,因为
for
循环不会这样做

您正在创建指向字符串文字的指针。在大多数/许多系统上,文本将被置于只读内存中

因此,您将在保护异常上设置SEGFULT[因为您试图写入只读内存]

此外,目标缓冲区需要足够大,以包含所有连接字符串的大小。如您所知,
a
太短/太小

你可以试试:

char a[100] = "1234567";

这将创建一个长度为100的可写缓冲区,并用字符串初始化。但是,您仍然有额外的空间来容纳连接的字符串[总长度不超过100]。

显示的代码试图将数据存储到未定义的缓冲区(
result
)中,这是不符合犹太教义的。必须有人通过传入有界输出缓冲区来分配空间,或者是函数,或者是调用方

使用分配内存机制,您必须提前获得所有字符串的完整大小,以便一次分配完整块。分配完整个区块后,一次复制一个字符串

char *concat3(const char *a, const char *b, const char *c)
{
    // get the required size in advance
    size_t n = 0;

    for (const char *ap = a; *ap; ap++) n++;
    for (const char *bp = b; *bp; bp++) n++;
    for (const char *cp = c; *cp; cp++) n++;

    char *result = malloc(n + 1);

    char *op = result;

    while (*op = *a++) op++;
    while (*op = *b++) op++;
    while (*op = *c++) op++;

    return result;
}
还要注意,参数是
const char*
而不是
char*
,以确保每个人都知道
concat3
-我更改了名称-不会写入这些输入缓冲区

但是,返回值不能是
const
,因为您必须释放它,我希望您记得这样做

EDIT我添加了一个不同的版本,该版本写入有界输出缓冲区,因此函数中不需要内存分配,因为调用方负责:

char *concat(char *obuf, size_t osize, const char *a, const char *b, const char *c)
{
    char *obuf_save = obuf;

    const char *obuf_max = obuf + osize - 1;

    while (obuf < obuf_max  &&  (*obuf = *a++)) obuf++;
    while (obuf < obuf_max  &&  (*obuf = *b++)) obuf++;
    while (obuf < obuf_max  &&  (*obuf = *c++)) obuf++;

    *obuf = 0;

    return obuf_save;
}
char*concat(char*obuf,size\u t osize,常量char*a,常量char*b,常量char*c)
{
char*obuf_save=obuf;
常量字符*obuf_max=obuf+osize-1;
而(obuf
关键部分是传递输出缓冲区和大小,它保证不会覆盖缓冲区的结尾


关键缺点:您无法判断它是否被截断。如果这很重要,则取决于您的应用程序。

char*result;结果[ir]=a[i]
不起作用<代码>结果
是未初始化的指针。取消引用这样的指针是未定义的行为。分配动态内存以返回或让调用者在缓冲区中传递。您已将
result
声明为指针,但它指向何处?目前,它完全没有初始化。您需要分配一些内存并指向它。您不会为
*结果
分配任何内存。您希望
结果[ir]
从何而来?你在未分配的内存中乱翻。你的复制代码也很奇怪。如果您解决了
result
不指向任何地方的问题,则仍然存在问题。第一个循环是可以的,尽管它不是显而易见的编写方式。第二个回路断开,第三个回路也断开。您应该对(i=0;a[i]!='\0';i++)结果[ir++]=a[i]ir
没有修改,并且(显然)在第二个和第三个循环中将
a
更改为
b
c
。您还需要
result[it]='\0'在第三个null循环后终止字符串。您是否知道动态内存分配和
malloc()
free()
等?如果你知道这一点,你可以用一种方法解决问题;如果你不这样做,你就得换一种方式。你和我一样误读了:
c
是一种输入,而不是输出。@SteveFriedl Yikes,你是对的。就目前而言,我发布的内容很好。我将编辑并添加附加信息。是的!在
concat
函数中没有写入(或试图写入)a[x]
b[x]
c[x]
。不错!但是:(1)为什么不
size\u t n=1
开始,在
malloc
中不再使用
n+1
。(2) 你在哪里把
NUL
终止符添加到
result
?我想到了
n=1char *concat3(const char *a, const char *b, const char *c)
{
    // get the required size in advance
    size_t n = 0;

    for (const char *ap = a; *ap; ap++) n++;
    for (const char *bp = b; *bp; bp++) n++;
    for (const char *cp = c; *cp; cp++) n++;

    char *result = malloc(n + 1);

    char *op = result;

    while (*op = *a++) op++;
    while (*op = *b++) op++;
    while (*op = *c++) op++;

    return result;
}
char *concat(char *obuf, size_t osize, const char *a, const char *b, const char *c)
{
    char *obuf_save = obuf;

    const char *obuf_max = obuf + osize - 1;

    while (obuf < obuf_max  &&  (*obuf = *a++)) obuf++;
    while (obuf < obuf_max  &&  (*obuf = *b++)) obuf++;
    while (obuf < obuf_max  &&  (*obuf = *c++)) obuf++;

    *obuf = 0;

    return obuf_save;
}