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

Serial.printf() with String object of which length is 11 or more

我的代码。

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) 向计算机发送字符串对象时,如果它的长度为 11 或更多,则发送奇怪的。

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

与长度无关

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

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

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

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

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

当你写:

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

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

当您构建程序时,编译器应该对传递给 printf() 的参数发出警告。阅读编译器输出的警告和错误可以减轻您的痛苦。