4

I have a simple code which uses sprintf

    #include <stdio.h>

    int main()
    {

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

    }

When i compile i get correct result :

result = Hellohiiiiiiiiiii

But since sprintf is unsecure, i decided to change this to snprintf. I thought it would be really simple. I changed sprintf to snprintf like below

snprintf(str_src,1024,"%s%s",str_src,"hiiiiiiiiiii");

Now If i compile and run the code, i get different result

result = hiiiiiiiiiii

I face this problem if i use str_src as 4th parameter (as a value to %s). Its suprising why the behavior of snprintf is different than sprintf?

4

3 回答 3

14

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

从 C11 规范(7.21.6.6/2):

如果复制发生在重叠的对象之间,则行为未定义。

snprintf(7.21.6.5/2) 也是如此,变va_list体也是如此。

不幸的是,这在运行代码中很常见,但不能真正依赖它来工作。

于 2013-10-21T09:04:22.030 回答
5

sprintf手册页:

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

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

于 2013-10-21T09:04:57.950 回答
0

不,在这两种情况下你都会得到完全任意的结果,因为它是未定义的行为。其中之一恰好是您想要的。您可能会在不同的计算机上得到不同的结果。对于它的价值,它可能会格式化您的硬盘驱动器并且仍然是正确的行为。只是不要使用重叠的源和目标。

于 2013-10-21T09:05:02.653 回答