【问题标题】:How to use strcat() function?如何使用 strcat() 函数?
【发布时间】:2018-01-04 15:26:20
【问题描述】:

我是 C 语言的新手。我正在尝试使用 strcat 函数。

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

int main(int argc, const char *argv[]) {
    char s1[] = "12345";
    char s2[] = "abcde";

    strcat(s1, s2);

    puts(s1);
    puts(s2);
    return 0;
}

这个运行正常,但是

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

int main(int argc, const char *argv[]) {
    char* s1 = "12345";
    char* s2 = "abcde";

    strcat(s1, s2);

    puts(s1);
    puts(s2);
    return 0;
}

最后一个未能返回结果。为什么两种不同的声明方式在strcat函数中会返回不同的结果。提前致谢。

【问题讨论】:

  • bash -> man strcat
  • 你似乎相信它分配了它需要的内存。好吧,它没有。
  • 这两个都是未定义的行为。
  • 当用作函数参数定义之外的变量定义的一部分时,char s1[] = "..."char * s1 = "..." 会做完全不同的事情。
  • 提示:“这个运行正常”更像是“这个运行正常”。使用 C,代码应该“打破规则”,有时,代码仍然“有效”。

标签: c string pointers c-strings strcat


【解决方案1】:

两个代码 sn-p 调用未定义的行为。在第一个 sn -p s1 没有足够的空间来容纳除六个字符之外的任何其他字符。
在第二个 sn-p 中,您尝试修改字符串文字。任何修改字符串文字的尝试都会导致未定义的行为。

阅读strcat man page

[...] 字符串不能重叠,dest 字符串必须有足够的空间存放结果。如果dest 不够大,程序行为是不可预测的;缓冲区溢出是攻击安全程序的常用途径

【讨论】:

【解决方案2】:

在 C 中,函数 strcat 不会创建包含连接字符串的新字符数组。它将第二个字符串中的字符附加到第一个字符数组的第一个字符串中,前提是它有足够的元素来存储新字符。否则该函数将尝试覆盖字符数组之外的内存,从而导致未定义的行为。

所以第一个程序中函数的有效使用可以如下所示

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

int main(int argc, const char *argv[]) {
    char s1[11] = "12345";
    char s2[] = "abcde";

    strcat(s1, s2);

    puts(s1);
    puts(s2);
    return 0;
} 

在这个程序中,字符数组被声明为有 11 个元素。因此它能够容纳附加的字符串"abcde"

在第二个程序中,尝试修改指针s1 指向的字符串文字。 C 和 C++ 中的字符串文字是不可变的。任何更改字符串文字的尝试都会导致未定义的行为,即使在与 C++ 字符串文字相反的 C 中具有非常量字符数组的类型。

来自 C 标准(6.4.5 字符串文字)

7 不确定这些数组是否是不同的,前提是它们的 元素具有适当的值。 如果程序试图 修改这样的数组,行为未定义。

所以在第二个程序中,您再次需要使用具有足够元素的字符数组。例如

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

int main(int argc, const char *argv[]) {
    char s1[11] = "12345";
    char* s2 = "abcde";

    strcat(s1, s2);

    puts(s1);
    puts(s2);
    return 0;
}

或者,如果编译器支持可变长度数组 (VLA),或者动态分配数组,您也可以使用它们。例如

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

int main(int argc, const char *argv[]) {
    char *s1 = "12345";
    char* s2 = "abcde";
    char s3[strlen( s1 ) + strlen( s2 ) + 1];    

    strcpy( s3, s1 );
    strcat( s3, s2 );

    puts(s1);
    puts(s2);
    puts(s3);

    return 0;
}

或者

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

int main(int argc, const char *argv[]) {
    char *s1 = "12345";
    char* s2 = "abcde";
    char *s3 = malloc( strlen( s1 ) + strlen( s2 ) + 1 );    

    if ( s3 != NULL )
    {
        strcpy( s3, s1 );
        strcat( s3, s2 );

        puts(s1);
        puts(s2);
        puts(s3);
    }

    free( s3 );

    return 0;
}

【讨论】:

  • IMO,替代语言讨论 (C++) 减损,特别是对于“我在 C 中很新”的 OP,从这个很好的 C 答案中,.建议删除或将替代语言讨论移到答案的后面部分。
  • 衷心感谢您的回答和耐心。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-26
  • 2013-07-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-19
相关资源
最近更新 更多