Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么字符串在strcat()之后被更改?_C_String_Output - Fatal编程技术网

为什么字符串在strcat()之后被更改?

为什么字符串在strcat()之后被更改?,c,string,output,C,String,Output,这是源代码 int main() { char str[]="dance"; char str1[]="hello"; char str2[]="abcd"; strcat(str1,str2); printf("%s",str); } 输出-bcd 为什么strcat(str1,str2)后str发生变化str1没有足够的空间连接字符串str2。这将调用未定义的行为。你可以得到任何东西。预期或意外结果。 现在试试这个: #include <std

这是源代码

int main()
{
    char str[]="dance";
    char str1[]="hello";
    char str2[]="abcd";
    strcat(str1,str2);
    printf("%s",str);
}
输出-
bcd

为什么
strcat(str1,str2)后
str
发生变化
str1
没有足够的空间连接字符串
str2
。这将调用未定义的行为。你可以得到任何东西。预期或意外结果。
现在试试这个:

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

int main(void) {
    char str[]="dance";
    char str1[10]="hello";
    char str2[]="abcd";
    strcat(str1,str2);
    printf("%s\n",str1);
    printf("%s\n",str);

    return 0;
}  
我得到了它。。。 由于我没有给出
str1
的大小,因此
str1
str
都会依次出现在内存中

所以当我连接str1和str2时,下面的事情发生了

a replaces \0
b replaces d
c replaces a
d replaces n
\0 replaces c
因此,
str
被改变

这是一种“未定义的行为”

str
str1
str2
的大小有限,它们被放入堆栈中,顺序取决于编译器。您的堆栈中可能有类似的内容

明白了吗


当您在
str1
的初始大小之后写入时,您将覆盖堆栈,这将更改堆栈上的所有其他变量。

您将
str2
连接到
str1
,但
str1
不够大,无法容纳这两个字符串。缓冲区溢出会损坏堆栈上第三个字符串的内容,
str

当你定义

char str1[] = "hello";
创建一个包含六个字符的数组,其中5个字符表示“hello”,另加一个空字符以终止字符串。可以说,字符串已经满了。快速修复方法是指定数组大小:

char str1[20] = "hello";
现在,您应该能够使用
strcat
str2
附加到
str1

实际上,您应该确保缓冲区足够大以容纳整个字符串:

char buf[20];

if (strlen(str1) + strlen(str2) < 20) {
    strcpy(buf, str1);
    strcat(buf, str2);
}

这可能会缩短整个字符串,但不会使缓冲区溢出。返回值
n
告诉您,如果有足够的空间,将写入多少个字符,因此您可以使用它进行检查。

尝试打印每个数组的大小,您应该自己得到答案,因为有4个字符(每个字节)分配给str1,4个字符分配给str2。因此,您正在覆盖str1的字节。我的理解是,所有三个字符串都应该是只读的,因为它们指向固定字符串,因此可能无法很好地定义在尝试写入这些数组时发生的情况。另外,str1必须长4个字节才能适合连接的字符串。为什么str会改变是个谜。三个指针(str、str1、str2)本身应该是读写的,但它们本身不是数组。可能堆栈上的指针本身已被覆盖和损坏。@PhilPerry:是的,
str
str1
str2
是数组,不是指针,我重复一遍。问题代码中没有指针对象。他们没有指向任何东西;它们包含(读/写)字符序列<代码>字符str[]=“舞蹈”
相当于
charstr[6]=“dance”str
str1
之后立即分配到内存中。
strcat
调用写入超过了
str1
的末尾,并将
str
关闭。这不是唯一可能的行为;这正是你(OP)在这种特殊情况下碰巧得到的。@GrijeshChauhan;现在它不会:)。是的,但请记住这不是C中定义的行为。@GrijeshChauhan:这是真的……我不能依赖这个事实……它在不同的计算机中是不同的,事实上,在不同的执行实例中可能是不同的@格里杰什乔汉:是的,这也是可能的,但我已经试过很多次了……还是一样result@GrijeshChauhan当前位置出于好奇,我想告诉你,我也是德尔希错人。堆栈上只有3个指针str、str1和str2(每个大约4个字节)。它们指向的三个字符数组位于其他位置,可能位于只读内存中(固定内容,不可更改)。他们在哪里,彼此之间的关系如何,都是你无法控制的。这一点仍然存在,因为str1的长度不足以容纳添加的额外文本(即使可以写入)。没有指针,只有数组,它们在堆栈中并排初始化,可能带有填充。
char str1[20] = "hello";
char buf[20];

if (strlen(str1) + strlen(str2) < 20) {
    strcpy(buf, str1);
    strcat(buf, str2);
}
char buf[20];
int n;

n = snprintf(buf, 20, "%s%s", str1, str2);