在我的Arduino草图中,我使用sprintf
来格式化回复。格式化的数据将使用SPI发送。
我必须设置缓冲区长度,但是我不知道有多大就好。这是一段代码:
uint8_t myValue = 4;
// Set buffer
unsigned char data[1000];
// Reset this buffer
memset(data, 0, sizeof(data));
// Format the reply
sprintf((char *)data, "This is the int value: %d", \
myValue);
我还可以将缓冲区设置为0(unsigned char data[0];
),代码将编译,并且答复与使用大缓冲区相同。我无法解释吗?
在Arduino世界中,malloc()
和free()
似乎很少见。
在Arduino中使用缓冲区的正确方法是什么?
答案 0 :(得分:1)
我建议改为使用snprintf
,在其中指定缓冲区的大小。使用当前方法,sprintf
假定缓冲区足够大,因此,如果将其传递给较小的缓冲区,它将占用其他一些内存。不好(可能会解释您有时会得到的奇怪结果)!
您可以像当前代码一样使用固定缓冲区。分配也可以,但是开销更大。
答案 1 :(得分:0)
我还可以将缓冲区设置为0(无符号字符数据[0];)
如果这是真的,那么您就是幸运的(或不幸的,取决于您的看法)。在C和C ++中,执行此操作的代码的行为均未定义。除此之外,这意味着它不能保证能正常工作(例如,如果您的编译器进行过更新,它可能会损坏)。
关于更好的选择....您的问题被标记为C ++和C,并且在不同的语言中最好采用不同的方法。
假设您正在使用C,并且您的实现符合1999年标准或更高版本,则可以使用snprintf()
。
char *buffer;
int length = snprintf((char *)NULL, 0, "This is the int value: %d", myValue);
buffer = malloc(length + 1); /* +1 allows for terminator */
snprintf(buffer, length, "This is the int value: %d", myValue);
/* use buffer */
free(buffer);
sprintf()
的第一次调用用于恢复缓冲区长度。第二个实际写入分配的缓冲区。完成后,请记住释放动态分配的缓冲区。 (以上内容也不检查错误-如果发生错误,snprintf()
将返回负值。)
如果您的C库中不包含snprintf()
,则(AFAIK)没有自动计算长度的标准方法-您将需要手工估算长度的上限(例如,计算长度的上限)。输出最大的负数或正数int
,并将其添加到格式字符串中其他内容的长度)。
在C ++中,使用字符串流
#include <sstream>
#include <string>
std::ostringstream oss;
oss << "This is the int value: " << myValue);
std::string str = oss.str();
const char *buffer = str.data();
// readonly access to buffer here
// the objects above will be cleaned up when they pass out of scope.
如果您坚持在C ++中使用C方法,那么如果您的实现符合2011标准(或更高版本),则可以在C ++中使用上面使用snprintf()
的方法。但是,总的来说,我不建议这样做。