sprintf()正在添加一个额外的变量

时间:2018-02-03 00:52:25

标签: c++ arduino

为什么会这样?:

char buf[256];
char date[8];
sprintf(date,  "%d%02d%02d", Time.year(), Time.month(), Time.day());
snprintf(buf, sizeof(buf), "{\"team\":\"%s\"}", team.c_str());
Serial.println(date);

输出:

20180202{"team":"IND"}

它应该只是:20180202 我不知道为什么{"team":"IND"}被添加到它的末尾。

2 个答案:

答案 0 :(得分:2)

很可能你声明了两个数组,它们的排列方式允许buf覆盖date的空终止符,因此它是“连接”两个。

我无法编写代码来重现这一点,因为它是未定义的行为,因此不可靠。但我可以告诉你如何避免它,

snprintf(date, sizeof(date), "%d%02d%02d", Time.year(), Time.month(), Time.day());
snprintf(buf, sizeof(buf), "{\"team\":\"%s\"}", team.c_str());

话虽如此,当你看来是c ++时,为什么要使用snprintf()?因此,针对此类问题有更合适的解决方案。

这会打印一个不正确的值,但不会导致任何意外的行为。

c中的字符串只是具有特殊排列的数组。如果字符串具有 n 可打印字符,则应将其存储在大小为 n + 1 的数组中,以便您可以添加所谓的 null 终结者。它是一个特殊值,表示字符串的 end

你的第二个snprintf()正在覆盖date数组的 null 终结符,因此似乎连接两个字符串。

答案 1 :(得分:0)

您已预留空间以准确存储8 char s:

char date[8];

正确存储日期20180202

char date[9];

因为sprintf()将额外的'\0'字符放到您传递的缓冲区中,以便正确进行c样式的字符串终止。

我怀疑你宣布你的缓冲区

char buffer[???];
char date[8];

由于这些很可能存储在处理器堆栈中,因此您需要向后读取,因此buffer处的输出将覆盖终止'\0'的输出,并在date之后立即显示。