String zu std:string, aber welche Vorteile?

Da ich darauf hingewiesen wurde, meine String variablen besser durch std::string zu ersetzen habe ich einen test sketch erstellt.
Leider erkenne ich hier keinen Vorteil in bezug auf den Speicher.
Welche Vorteile ergeben sich nun daraus?

String:
3336 Bytes Programmspeicher
224 Bytes dynamischer Speicher

std::string:
4826 Bytes Programmspeicher
439 Bytes dynamischer Speicher

//#define USESTL   //Uncomment to use.

#define STARTSTR "Str VS str:"

#ifdef USESTL
  #include <ArduinoSTL.h>     
  std::string test = "std::string:";
  std::ohserialstream sout(Serial);
#else
  String test = "String:"; //+ STARTSTR;
#endif

void printtest()
{
  #ifdef USESTL
    sout << test << std::endl;
  #else
    Serial.println(test);
  #endif
}

void setup() {
  //Initialize serial and wait for port to open:
  test += STARTSTR;
  Serial.begin(38400);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  printtest();
}


void loop() {
  if (Serial.available())
  {
    test += (char)Serial.read();
    printtest();
  }
  
}

Da ich darauf hingewiesen wurde, meine Sting variablen besser durch std::string zu ersetzen

Das kann ich mir kaum vorstellen....

Denn die Arduino String Klasse wurde als schlankere/spezialisierte Alternative zu std::string entwickelt.

std::string kann seine Vorteile ausspielen, wenn du Software für PCs oder ähnliche Geräte entwickelst.
Auf unseren kleinen AVRs ist es nicht ohne Grund deaktiviert.

Ich möchte dafür wetten, dass dir empfohlen wurde, Strings im C Stil zu verwenden!
Stimmt es, oder habe ich recht?

Wenn man nach der Referenzseite geht, dann sollst Du anstelle String() als Objekt lieber String als Zeichenkette verwenden.

hab ich das dann tatsächlich falsch verstanden? millis(), goto, constant, and String. · Issue #1 · harryberlin/Arduino-BMW-IBus-SerialInterface-MCP2025 · GitHub

dann hab ich es doch eh schon richtig gemacht, oder? hab nirgends die klammern nach String verwendet.

Da steht doch dort was gemeint ist:

A array of 'char' would be the best choice.

Genauer: ein Null-terminiertes char Array. Auch "C string" genannt

Und die Speicherverschwendung ist nicht das einzige Problem. Die String Klasse ist auch in ihrer Funktionalität stark eingeschränkt. Vor allem bei Formatierungs- und Konvertierungs-Funktionen

Die Bibliothek ist doch etwas zweifelhaft. Da sieht man auch sowas:

int hexToDec(String hexString)

Ein Objekt wird als Wert statt als Referenz übergeben. Das deutet doch sehr auf fehlende Programmierkenntnisse hin

ok, dann hab ich das völlig falsch verstanden. :open_mouth:
gut dass wir drüber gesprochen haben.

ja, ich bin noch nicht sehr bewandert mit programmierung von arduinos. dennoch gewillt es besser zu machen.

Dazu ist unsere Hilfa ja da.
Grüße Uwe

#define wake_set(...) digitalWrite(WAKE_PIN, __VA_ARGS__)

Das ist etwas falsch, denke ich mal....

denn z.B. ein wake_set(1,2); meldet:

too many arguments to function 'void digitalWrite(uint8_t, uint8_t)'

schlagt mich, aber ich krieg es nicht sowas simples hin, chars zusammen zu setzen oder von einer function einen char* zurück zu kriegen.

char test[0];


const char * decToHex(const byte &decValue) {

  char hexString[0];
  sprintf(hexString, "%02X", decValue);
  return hexString;
  
}


void setup() {  
  
  
  Serial.begin(38400);
  
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  

  strcat(test, decToHex(15));
  
  strcat(test, "ttt");
  Serial.println(test);
  strcat(test, "jjj");
  
  Serial.println(test);
  
}


void loop() {
  if (Serial.available())
  {
    strcat(test,(char)Serial.read());
    
    Serial.println(test);
    
  }
  
}

@combie
Doch das geht, du musst nur LOW oder HIGH übergeben. arg1 ist nicht nötig. WAKE_PIN ist voerher definiert.

Wenn Du ein lokales Chararray der Länge 0 anlegst und dort 3 Zeichen rein schreiben willst, ist das schon mal auch ohne Kenntnisse völlig unlogisch.
Die lokale Variable hexString existiert nach der Rückkehr nicht mehr, also ist das der 2. Fehler.

Du solltest Dich mal mit den Grundlagen von Zeichenketten beschäftigen.

Gruß Tommy

const char * decToHex(const byte &decValue) {

  char hexString[0];
  sprintf(hexString, "%02X", decValue);
  return hexString;
  
}

Au, au. Da wird wieder mal ein Zeiger auf eine lokale Variable zurückgegeben.

Und was soll ein Array der Länge 0 überhaupt sein?

Ein einzelnes Byte oder einen Integer kannst du auch per Wert übergeben. Aber bei einem Objekt sollte man das nicht tun (ein leeres String Objekt belegt schon 6 Bytes).

Dass strcat() nicht dazu da ist einzelne Zeichen anzuhängen sieht man schon an der Signatur der Funktion

Die Konvertierung nach Hex kann man auch leicht per Hand machen. Da muss man nicht eine sehr umfangreiche Funktion wie printf() bemühen. Ansonsten gibt es auch noch itoa() dafür

@Tommy56
woher soll ich wissen wir lang der string wird, wenn ich noch gar nicht weiß was ich rein schreibe?
wenn ich in setup() char test[0] erstelle geht es aber.

@Serifly
wenn ich return itoa(decValue); nehme kommt ein compilierfehler

too few arguments to function 'char* itoa(int, char*, int)'

woher soll ich wissen wir lang der string wird, wenn ich noch gar nicht weiß was ich rein schreibe?

Man weiß meistens wie lang der String maximal werden kann

wenn ich in setup() char test[0] erstelle geht es aber.

Nur weil der Compiler etwas erlaubt heißt dass nicht dass es richtig ist oder dass sich das Program richtig verhält

https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html

wenn ich return itoa(decValue); nehme kommt ein compilierfehler

Du tippst also nur wild Code ein ohne dir mal die Beschreibungen der Funktionen durchzulesen

Und auch hier erwartest du irgendwie dass dir eine Funktion auf magische Art Speicher liefert. So geht das nicht! Bei diesen C Funktion musst du ein ausreichend großes Array als Parameter übergeben. Wenn die Funktionen einen Zeiger als Rückgabewert hat dann ist dass ein Zeiger auf das Array das man von außen übergeben hat

@harryberlin: Bei der von Dir zur Schau gestellten Unwissenheit, die Du aber um jeden Preis verteidigst, solltest Du Dir ein anderes Hobby suchen. Du zeigst, dass Du nicht gewillt bist etwas zu lernen.

Gruß Tommy

harryberlin:
@combie
Doch das geht, du musst nur LOW oder HIGH übergeben. arg1 ist nicht nötig. WAKE_PIN ist voerher definiert.

Das weiß ich doch!

Dann formuliere ich das mal um:
Du hast da ein Variadic Macro geschaffen.
Wozu?
Die Eigenschaft darf nicht genutzt werden, und das habe ich dir eben präsentiert.
Damit ist die Definition falsch.
Ein semantischer Fehler.

Und ich möchte nicht, dass sich hier "jeder Anfänger" den Fehler abschaut....

Denke bitte nicht, dass ich grundsätzlich was gegen Variadic Macros habe, denn das stimmt nicht.
Ich habe allerdings grundsätzlich was gegen jede Art von unnötigem Macro!
Und das ist hier der Fall: Unnötig!

Tipp:
Setze den Präprozessor nur für Angelegenheiten ein, die C++ nicht von sich aus leisten kann.

Meine Regel:
Jedes vermiedene #define ist ein gutes #define.
Jedes vermeidbare #define ist ein böses #define

so jetzt. als return geht das gar nicht, oder?

mit itoa bin ich nicht so ganz zufriden, weil dann die 0 für das zweistellige HEX fehlt. und uppercase ist es auch nicht.

char test[100];


int decToHex(const byte &decValue, char *target) {
  char hexString[3];  
  //itoa(decValue, hexString, 16);
  sprintf(hexString, "%02X", decValue);
  strcat(target, hexString);  
  return 0;
}


void setup() {  
  Serial.begin(38400);
  
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  
  decToHex(15, test);
  Serial.println(test);
  
  strcat(test, "ttt");
  Serial.println(test);
  strcat(test, "jjj");
  
  Serial.println(test);
  
}

Warum nicht einfacher:

char *decToHex(const byte &decValue) {
  static char hexString[3]; // static, damit es erhalten bleibt
  sprintf(hexString, "%02X", decValue);
  return hexString;
}

Gruß Tommy

als return geht das gar nicht, oder?

Doch. Du musst nur das Array zurückgeben dass du übergeben hast. Was nicht ist Zeiger auf lokale nicht-statische Variablen zurückgeben

// static, damit es erhalten bleibt

Aua!
Damit kann man sich ganz fix unbeabsichtigte Seiteneffekte einfangen.

Welche?

Gruß Tommy