Variablenübergabe

Moin,

Ich habe hier folgende Funktion:

void printUserData(const struct UserData* userData) {
  Serial.print("color = ");  Serial.println(userData->color);
}

Diese Funktion wird von diesem Teil angesprochen:

if (connect(server)) {
  if (sendRequest(server, resource) && skipResponseHeaders()) {
    UserData userData;
    if (readReponseContent(&userData)) {
      printUserData(&userData);
    }
  }
}

Nun habe ich eine Schleife um den Teil gelegt und möchte ich anstatt des Funktionsaufrufes “printUserData” den Inhalt von userdata in ein Array textcol[pos] schreiben:

for (int pos=0; pos<7; pos++){    // Schleife 0-6
  if (connect(server)) {
    if (sendRequest(server, resource) && skipResponseHeaders()) {
      UserData userData;
      if (readReponseContent(&userData)) {
        textcol[pos]=(&userData);
        // printUserData(&userData);
      }
    }
  }
}

Leider gelingt dies nicht.
Die Fehlermeldung lautet:
exit status 1
invalid conversion from ‘UserData*’ to ‘uint16_t {aka short unsigned int}’ [-fpermissive]

Die Variablen sind folgendermaßen deklariert:

uint16_t textcol[8];

struct UserData {
  char color[8];
};

Vermutlich passt das Format nicht und muss irgendwie umgewandelt werden?

Wer weiss Rat?

Danke und lieben Gruß,
Chris

:confused:

Das hatten wird doch gerade erst. Genau dafür ist die rgb565() Funktion! Die nimmt einen C String als Parameter und liefert einen 16 Bit Integer

Erst machst du ein Thread auf wie du diese Funktion korrekt aufrufst und jetzt willst du sie nicht mehr verwenden?

Erst machst du ein Thread auf wie du diese Funktion korrekt aufrufst und jetzt willst du sie nicht mehr verwenden?

Doch, natürlich!
.....Wie war das mit dem Wald und den Bäumen.....?!

Also so?:

textcol[pos]=rgb565(&userData);

Da steigt er aus mit

exit status 1
cannot convert 'UserData*' to 'const char*' for argument '1' to 'uint16_t rgb565(const char*)'

Schau mal in Dein eigenes Posting im anderen Thread. Da ist der Aufruf drin.

Gruß Tommy

Ich verstehe nicht wieso du da ein Problem hast. In dem anderen Thread hast du es doch korrekt aufgerufen!

textcol[pos]=rgb565(userData->color);

Wieso klappt das jetzt nicht mehr?

Liegt es daran dass userData an der Stelle ein Objekt ist und kein Zeiger? Dann so:

UserData userData;

...

textcol[pos]=rgb565(userData.color);

Das mit -> ist für den Fall dass userData ein UserData* (Zeiger auf das struct) ist. Dann muss man den Zeiger erst dereferenzieren

Es würde dich weniger verwirren wenn die Funktionen nicht einen Zeiger auf ein struct als Parameter hätten, sondern eine Referenz. Dann muss man bei der Übergabe nicht die Adresse mit & übergeben, sondern der Aufruf ist ganz normal. Und der Zugriff erfolgt nicht mit -> sondern wie normal mit .
Der Grund weshalb das call-by-reference übergeben wird ist damit beim Aufruf keine Kopie angelegt wird. Das wäre schlecht. Früher in C gab es da nur Zeiger. Aber in C++ gibt es auch Referenzen die syntaktisch etwas einfacher zu handhaben sind

Aber Grundlagen musst du schon etwas lernen. Dass du das mit den Zeigern nicht verstehst ist ok. Das ist eine C Eigenheit und nicht ganz einfach. Aber Datentypen gibt es auch in anderen Sprachen. Du hast eine Funktion die einen C String möchte. Du hast ein struct dass einen C String enthält. Also musst du den String übergeben und nicht das struct oder dessen Adresse (& bedeutet "Adresse von"). Den Zusammenhang von "was habe ich an Daten" zu "was will die Funktion" musst du erkennen. Das sieht man an den Datentypen der Variablen, Parameter und Rückgabewerten

Liegt es daran dass userData an der Stelle ein Objekt ist und kein Zeiger? Dann so:
UserData userData;
...
textcol[pos]=rgb565(userData.color);

Genau das war das Problem!
Der Pointer hat gefehlt.
Alter Schwede, das soll eine verstehen?!

Aber es wird und wird und wird immer besser :slight_smile:

Vielen Dank nochmal!
Lieben Gruß,
Chris

Der Pointer hat gefehlt.

Der Punkt vielleicht. Pointer = Zeiger. Das ist was anderes

Ist ganz einfach. Normal greift man auf Elemente mit . zu. Wenn man einen Zeiger hat mit ->

Am besten du änderst deine Funktionsaufrufe wo structs übergeben werden.

void printUserData(const struct UserData* userData)
bool readReponseContent(struct UserData* userData)

Wird zu;

void printUserData(const struct UserData& userData)
bool readReponseContent(struct UserData& userData)

Und die Zugriffe auf userData darin von -> zu .
Das ist was ich oben gemeint habe. Ohne Zeiger greift man auf die Elemente des structs mit dem Punkt zu!

Bei der Übergabe muss man dann nicht mehr & (Adresse von) schreiben. Also z.B. hier:

      if (readReponseContent(&userData)) {
        printUserData(&userData);

Zu:

      if (readReponseContent(userData)) {
        printUserData(userData);

Dadurch ist der Unterschied zwischen Call By Value und Call By Reference nur ein einzelnes Zeichen (das & beim Parameter)

Das ist eine reine Syntax-Vereinfachung. Gemacht wird das gleiche.
Zeiger haben schon ihre Berechtigung. Man kann mit denen Dinge machen die mit Referenzen nicht gehen (z.B. das mit der Addition von 1 um ein Zeichen zu überspringen). Aber hier braucht man sie nicht.

Klassischerweise würde man Funktionen mit einem Parameter (struct UserData* userData) zu Funktionen der Klasse UserData machen, damit wäre der Parameter ein impliziter struct UserData* this.

Whandall:
Klassischerweise würde man Funktionen mit einem Parameter (struct UserData* userData) zu Funktionen der Klasse UserData machen, damit wäre der Parameter ein impliziter struct UserData* this.

Die Arduino IDE hat da auch mit dem Printable Interface eine nette Sache um beliebige Klassen direkt an print() zu übergeben. Ist aber versteckt, nicht dokumentiert und wird kaum verwendet.

Aber wenn er schon mit solchen Grundlagen diese Probleme hat ist das zu viel des Guten :slight_smile: