"C语言中的strcat函数混淆假设目标字符串足够大,可以保存源字符串及其自身的内容."

Kar*_*lar 2 c string strcat

所以我读到该strcat函数将被仔细使用,因为目标字符串应该足够大以容纳其自己和源字符串的内容.我写的以下程序也是如此:

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

int main(){
    char *src, *dest;
    printf("Enter Source String : ");
    fgets(src, 10, stdin);
    printf("Enter destination String : ");
    fgets(dest, 20, stdin);
    strcat(dest, src);
    printf("Concatenated string is %s", dest);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但对于我在这里写的那个不是这样的:

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

int main(){
    char src[11] = "Hello ABC";
    char dest[15] = "Hello DEFGIJK";
    strcat(dest, src);
    printf("concatenated string %s", dest);
    getchar();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

该程序最终添加两者而不考虑目标字符串不够大.为什么会这样?

dbu*_*ush 10

strcat函数无法确切知道目标缓冲区的长度,因此它假定传递给它的缓冲区足够大.如果不是,则通过写入缓冲区的末尾来调用未定义的行为.这就是第二段代码中发生的事情.

的代码的第一块也是无效的,因为这两个srcdest是未初始化的指针.当您将它们传递给fgets它时,它会读取它们包含的任何垃圾值,将其视为有效地址,然后尝试将值写入该无效地址.这也是未定义的行为.

使C快速的一个原因是它不会检查以确保您遵守规则.它只是告诉你规则,并假设你遵循它们,如果你没有坏事,可能会或可能不会发生.在你的特殊情况下,它似乎工作,但不能保证.

例如,当我运行你的第二段代码时,它似乎也有效.但如果我改成它:

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

int main(){
    char dest[15] = "Hello DEFGIJK";
    strcat(dest, "Hello ABC XXXXXXXXXX");
    printf("concatenated string %s", dest);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

程序崩溃了.


Ste*_*mit 7

我认为你的困惑实际上并不是关于它的定义strcat.您真正的困惑是您认为C编译器会强制执行所有"规则".这个假设是非常错误的.

是的,第一个参数strcat必须是一个足以存储连接结果的内存指针.在您的两个程序中,都违反了该要求.你可能会从任何一个程序中缺少错误消息得到这样的印象:也许规则不是你想象的那样,strcat即使第一个参数不是指向足够内存的指针,它也会以某种方式调用.但不是,情况并非如此:strcat当内存不足时调用肯定是错误的.没有错误消息,或者一个或两个程序似乎"正常"的事实证明没有任何证据.

这是一个类比.(你小时候甚至可能有这种经历.)假设你的母亲告诉你不要跑到街对面,因为你可能会受到汽车的撞击.无论如何,假设你跑到街对面,不要被车撞到.你是否认为你母亲的建议不正确?这是一个有效的结论吗?

总而言之,您所阅读的内容是正确的:strcat必须谨慎使用.但是,让我们重申一下:打电话时一定要小心strcat.如果你不小心,各种各样的事情都可能出错,没有任何警告.事实上,许多风格指南建议不要使用任何功能strcat,因为如果你不小心,它们很容易被误用.(strcat只要你小心,这些功能可以完全安全地使用 - 当然并非所有程序员都非常小​​心.)

  • 很好的比喻 (2认同)