为什么当我们使用相同的源和目标时,sprintf和snprintf的行为是不同的?

Nas*_*sir 2 c printf

我有一个使用sprintf的简单代码

    #include <stdio.h>

    int main()
    {

            char str_src [1024]={"Hello"};
            sprintf(str_src,"%s%s",str_src,"hiiiiiiiiiii");
            printf("result = %s",str_src);  

    }
Run Code Online (Sandbox Code Playgroud)

当我编译我得到正确的结果:

结果= Hellohiiiiiiiiiii

但由于sprintf不安全,我决定将其更改为snprintf.我觉得这很简单.我将sprintf更改为snprintf,如下所示

snprintf(str_src,1024,"%s%s",str_src,"hiiiiiiiiiii");
Run Code Online (Sandbox Code Playgroud)

现在,如果我编译并运行代码,我会得到不同的结果

结果= hiiiiiiiiiii

如果我使用str_src作为第四个参数(作为%s的值),我将面临这个问题.令人惊讶的是为什么snprintf的行为与sprintf不同?

Som*_*ude 11

使用相同的缓冲区作为目标和源是未定义的行为.

从C11规范(7.21.6.6/2):

如果在重叠的对象之间进行复制,则行为未定义.

对于snprintf(7.21.6.5/2)也是如此,并且对于va_list变体也是如此.

不幸的是,它在运行代码时很常见,但它并不能真正依赖于工作.


Fil*_*ves 5

sprintf联机帮助页:

C99 和 POSIX.1-2001 指定如果调用 sprintf()、snprintf()、vsprintf() 或 vsnprintf() 会导致在重叠的对象之间进行复制(例如,如果目标字符串数组和提供的输入参数之一引用同一个缓冲区)。见注释。

这个问题真的没有答案,因为您的代码具有未定义的行为。