printf()函数如何处理函数使用全局缓冲区返回的字符串?

Don*_*rer 7 c string printf function return-value

我写了一个小代码,用特定格式打印当前日期.要返回日期的每个数据(星期几,月中的某天,月份的名称等),我使用const char*类型的函数将数据作为字符串传递给充当缓冲区的变量然后将缓冲区传递给main函数.

以下代码以非常简单的方式表示我的程序的操作:

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

char
buff[16];

const char
*printStr1 (char *str1)
{
    strncpy(buff, str1, sizeof(str1));
    return buff;
};

const char
*printStr2 (char *str2)
{
    strncpy(buff, str2, sizeof(str2));
    return buff;
};


int
main()
{
    printf("%s%s", printStr1("foo"), printStr2("bar"));
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:当将每个数据传递给缓冲区并将其返回到main函数时,最后两个数据是相同的(最后一个数据不打印,而是打印已经存在于缓冲区中的数据,即倒数第二个数据).

这只发生在我使用单个printf()函数来显示所有数据时,如上例所示.如果我不使用缓冲区返回数据(我直接返回传递给函数的参数)或对每个数据使用printf(),一切都正确执行.

PS:我试图用memset()这样的函数来解决这个问题来清理缓冲区,但它不起作用,我唯一能做的就是为每个数据使用不同的缓冲区(对于每个函数).

我希望我能很好地表达我的问题.

Jea*_*bre 10

除了sizeof问题(因为你的字符串很小而忽略了),你的问题与之无关printf

代码首先评估参数,然后将它们传递给printf.最后一个评估的参数"wins"并printf获得两次相同的参数.

要仅使用一个本地缓冲区,请拆分您的printf呼叫:

printf("%s%s", printStr1("foo"), printStr2("bar"));
Run Code Online (Sandbox Code Playgroud)

可以改写为:

printf("%s", printStr1("foo"));
printf("%s", printStr2("bar"));
Run Code Online (Sandbox Code Playgroud)

一旦打印出来的价值可以改变它没关系:)

由于C没有垃圾收集器或字符串对象,因此您不能只分配单独的缓冲区并返回它们以传递给printf其他内存泄漏,因此在C中没有针对此类问题的智能和可读解决方案.

也就是说,在我制作的一个C项目中,我使用了一个循环的字符串列表(几个缓冲区,先进先出).使它成为10个缓冲区,并且您可以在同一个函数中使用多达10个参数,它将正常工作.


Jab*_*cky 6

这段代码:

printf("%s%s", printStr1("foo"), printStr2("bar"));
Run Code Online (Sandbox Code Playgroud)

相当于:

const char *p1 = printStr1("foo");
const char *p2 = printStr2("bar");
printf("%s%s", p1, p2);
Run Code Online (Sandbox Code Playgroud)

或者这(取决于编译器):

const char *p2 = printStr2("bar");
const char *p1 = printStr1("foo");
printf("%s%s", p1, p2);
Run Code Online (Sandbox Code Playgroud)

现在应该清楚为什么你得到你得到的输出.