Serial.printf() 带有长度为 11 或更多的 String 对象

问题描述

我的代码

void loop() {
  if(Serial.available()) {
    String str = Serial.readStringUntil('\n');
    Serial.printf("String1:%s\n",str);
    Serial.print("String2:");Serial.println(str);
    Serial.printf("char*:%s\n",str.c_str());
  }
}


使用串行发送 1234567890。 (长度10)

String1:1234567890
String2:1234567890
char*:1234567890


使用串行发送 12345678901。 (长度11)

String1:@��?
String2:12345678901
char*:12345678901

当我使用 Serial.printf("%s") 从 arduino(esp32) 向计算机发送 String 对象时,如果其长度为 11 或更大,则发送奇怪的内容

String str = "12345678901";
Serial.print(str); // ok
Serial.println(str); // ok
Serial.printf(str); // incorrect Syntax
Serial.printf("%s",str); // error

解决方法

与长度无关。

这是因为您将 String 对象传递给 %s 中的 Serial.printf() 格式。

A String 不是 C 字符串。 %s 中的 printf() 格式旨在处理 C 字符串 - 它获取与其对应的值并将其视为 char * - 指向以空字符结尾的字符数组的指针,这就是语言 C 表示字符串的方式。

%s 不适用于 String 对象。因此该行:

    Serial.printf("char*:%s\n",str.c_str());

确实有效,因为您在 c_str() 对象上调用了 String 方法以获取指向其底层 C 字符串的指针。

当你写作时:

    Serial.printf("String1:%s\n",str);

您的程序将打印 str 对象的二进制内容,就好像它是一个 C 字符串,但事实并非如此。你很幸运它没有崩溃。

当您构建程序时,编译器应该就传递给 printf() 的参数给出警告。阅读编译器输出的警告和错误可以为您省去一些麻烦。