C中使用strcat的坑

本文解释了C语言中strcat函数如何连接字符串,并指出当目标字符串空间不足时可能导致的长度异常和内容改变。同时强调了正确处理字符串内存和使用strncat以防止缓冲区溢出的重要性。
摘要由CSDN通过智能技术生成

首先理解:

        strcat(s1, s2): 连接字符串 s2 到字符串 s1 的末尾。

        就是拼接俩个字符串, 但仅仅这样么??????????????

看我的代码:

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

int main(){
    char s1[] = "hello";
    char s2[] = "world";
    char s3[] = "cokie";
    printf("strlen(s1) s1: %d\n", strlen(s1));
    printf("strcat(s2, s3) s2: %s\n", strcat(s2, s3));
    printf("strlen(s1) s1: %d\n", strlen(s1));
    printf("s1: %s\n", s1);
    return 0;
}

再看执行结果

strlen(s1) s1: 5
strcat(s2, s3) s2: worldcokie
strlen(s1) s1: 4
s1: okie

请按任意键继续. . .

我去, 我的s1的长度咋变了, 值也变了???????????????

来看讲解(来自[文心一言]):

在C语言中,执行上述代码时,strlen(s1)两次获取的长度不一致,并且最后打印s1时,s1的值发生了变化,这主要是由于strcat函数的特性以及字符数组在内存中的布局所导致的。

首先,让我们看看strcat函数的工作原理。strcat函数用于连接两个字符串。它将第二个字符串(及其终止的null字符)追加到第一个字符串的结尾,直到第一个字符串的\0字符为止。这意味着strcat会修改其第一个参数指向的字符串。

在你的代码中:

char s1[] = "hello";
char s2[] = "world";
char s3[] = "cokie";

你定义了三个字符数组,并分别初始化为"hello"、"world"和"cokie"。

接下来,你调用strcat(s2, s3)

printf("strcat(s2, s3) s2: %s\n", strcat(s2, s3));

这会将s3的内容("cokie")追加到s2的内容("world")的末尾,所以s2现在包含"worldcokie"。重要的是,strcat会修改s2的内容,而s2s3的内容在内存中是相邻的(尽管没有直接的保证,但在大多数实现中是这样)。

问题出在strcat可能无意中覆盖了s1的内容。由于s1s2s3都是在栈上分配的,并且可能相邻,strcat在寻找s2的结束位置(即\0字符)时可能会越过s2的边界,进入s3的内存区域,然后继续在栈上寻找\0。如果在这个过程中它覆盖了s1的结束null字符,那么s1的字符串就会变长,因为它不再以null字符结尾。

因此,当你第一次调用strlen(s1)时,s1仍然以null字符结尾,所以长度是5(对应"hello"的长度)。但是,在调用strcat(s2, s3)后,s1的结束null字符可能已经被覆盖,导致strlen(s1)在寻找新的null字符时越过了"hello"的范围,得到了一个更大的长度。

最后,当你打印s1时:

printf("s1: %s\n", s1);

printf会使用%s格式化说明符,该说明符期望一个以null字符结尾的字符串。由于s1现在可能不再以null字符结尾,或者null字符的位置已经改变,printf会继续打印内存中的字符,直到它偶然遇到一个null字符为止。这可能导致输出包含s2s3的部分内容,或者其它栈上的内存内容,造成未定义行为。

为了避免这种问题,你应该确保在使用strcat时,目标字符串(在这里是s2)有足够的空间来容纳源字符串(在这里是s3)的内容,包括额外的null字符。通常,这意味着你应该为目标字符串分配足够的空间,或者在调用strcat之前检查是否有足够的空间。在实际编程中,更安全的做法是使用strncat函数,它允许你指定一个最大字符数来避免缓冲区溢出。

此外,为了避免未定义行为,你应该总是确保字符串以null字符结尾,并且在访问或打印字符串之前检查它们是否确实以null字符结尾。这通常是在分配或修改字符串后通过显式设置null字符来完成的。
 

我知道,我偷懒了, 但是问题找到了, 不是吗,哈哈哈哈
解决方法:

        1. 确保在使用strcat时,目标字符串(在这里是s2)有足够的空间来容纳源字符串(在这里是s3)的内容, 包括null字符

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值