Verständnisproblem bei Programmierung, es klappt, aber ich weiß nicht warum

Ihr seid beide mit den Referenzen in C++ unterwegs.

Wenn allerdings der Code, den skyfox60 hier angegeben hat, aus einer ähnlichen Quelle wie diese hier stammt, ist das an der Stelle pures C (mit Zeigern, also nicht "per value").

int temp = 20, temp_mittel=200;

void setup() {
...
  bmp085_read_temperature_and_pressure(&temp_mittel,&druck_mittel); // erstmal Mittelwerte lesen
}

void loop() {
  bmp085_read_temperature_and_pressure(&temp, &druck); // dauert ca. 34ms
...
}

void bmp085_read_temperature_and_pressure(int* temp, long* druck) {
...
  *temp = (b5 + 8) >> 4;
...
  *druck = p + ((x1 + x2 + 3791) >> 4);
}

ist das an der Stelle pures C (mit Zeigern, also nicht "per value").

Das ist C++!
Auch dein Beispiel.
Der Beweis: Es wird durch einen C++ Kompiler genudelt.

Ein Übergabe per Zeiger gibt es nicht.
Aber es gibt die Übergabe von Zeigern.
Und Zeiger werden in der Regel per Value übergeben.

Man könnte allerdings auch Zeiger auf Zeiger oder Referenzen von Zeigern übergeben, wenn man scharf darauf ist.

combie:
Der Beweis: Es wird durch einen C++ Kompiler genudelt.

Okay, ich gebe mich geschlagen.

Off Topic:

Zeiger auf Zeiger

Habe ich schon Geld mit verdient. Allerdings unter Verwendung eines C-Compilers :wink:

Also die Quelle, die dort angegeben war, ist vermutlich die gleiche, die der programmer seinerzeit genutzt hat.

Die drei Beispiele "hochdrei_1 bis 3 hab ich mir mal angeschaut.

Ja, die Ergebnisse sind unterschiedlich, ich muss aber zugeben, das ich das nicht wirklich verstanden habe.

So wird mir beispielsweise überhaupt nicht klar, wie das b dort eine Verbindung zum x, und das c eine Verbindung zum y hat/aufbaut/sieht/bekommt.

Nach meinem bisherigen verständnis könnte die Maschine gar nicht wissen, das x irgendwie nach B soll, z.B. durch x=b oder ähnlich.

Da hab ich glaube ich noch sehr große Lücken im Verständnis.
Mir schwant was, aber ich ich z.B. nicht in der Lage, das anderweitig sinnvoll zusammen zu stricken.
Höhere Mathe ist einfach zu lange her.

Trotzdem hat es aber ein wenig meinem Verständnis für das Programm geholfen.
Danke euch allen für die Erklärungen.

Das Programm ist übrigens ein Variometer, das mir per Funk Steigen und Sinken im Flugzeug nach unten funkt, so das ich mit dem Segler die Thermik besser finden, erkennen und nutzen kann.

Das Programm entzieht sich so an einigen Stellen meinem Verständnis.

Sinken wird mit Dauerton gemeltet, dessen Tonhöhe mit zunehmender Sinkgeschwindigkeit tiefer wird.

Steigen wird gemeldet durch einen unterbrochenen Ton, bei dem mit zunehmender Steigeschwindigkeit sowohl die Tonhöhe steigt, als auch die Ton - Pulsfrequenz. Also hellerer Ton und piept schneller.

Ich habe gesucht und gesucht, und bekopmme nicht raus, wie dort die Druckänderung über die Zeit ( den Wert braucht man ja dafür) ermittelt wird. Schon kleinste Änderungen über wenig Zeit(<1S) werden zuverlässig angezeit. Es reicht, das Ding in der Hand zu halten, und den Arm auf, bzw ab zu bewegen.

Für mich sehr nützlich, aber es bleibt ein mystisches Etwas.
Den Sketch hatte ich aus einem holländischen Modellbauforum. Die Sprache beherrsche ich erheblich besse, als C oder C++. :slight_smile:

skyfox60:
Den Sketch hatte ich aus einem holländischen Modellbauforum. Die Sprache beherrsche ich erheblich besse, als C oder C++. :slight_smile:

Dann solltest Du Dich intensiv mit C++ beschäftigen. Hier ein sehr gutes Buch.

Fehlerkorrektur im Kommentar:

void hochdrei_3(int &x, int &y) {  // x und y sind Referenzen und verändern auch b und c
  y = x * x * x;                   // dies verändert auch c
  x = x * x;                       // dies verändert auch b
}

skyfox60:
Die drei Beispiele "hochdrei_1 bis 3 hab ich mir mal angeschaut.

Dann habe ich es ja nicht umsonst gemacht :slight_smile:

skyfox60:
So wird mir beispielsweise überhaupt nicht klar, wie das b dort eine Verbindung zum x, und das c eine Verbindung zum y hat/aufbaut/sieht/bekommt.

Ganz simpel über die Reihenfolge, also die Position innerhalb der runden Klammern. Zusätzlich müssen die Typen übereinstimmen, also int zu int, uint32_t zu uint32_t und so weiter. Bei return gibt es einen Rückgabewert.

skyfox60:
Nach meinem bisherigen verständnis könnte die Maschine gar nicht wissen, das x irgendwie nach B soll, z.B. durch x=b oder ähnlich.

Die Maschine, also der Mikroprozessor, bekommt Maschienencode in seinen Speicher geladen, da würden wir beide die Stelle nur mit Schwierigkeiten wiederfinden. Schlaue Menschen wie RudiDL5 (Gruß an Rudi!) fühlen sich in dieser Materie dann erst richtig wohl.

Du meinst Präprozessor, Linker, Kompiler und alle Helferlein, die von der IDE verwendet werden. Wenn ich ein paar funktonierende Programmzeilen zusammengebracht habe, könnte ich die Welt vor Freude umarmen. Wenn Dein Flugzeug die richtigen Töne abgibt, freust Du Dir ein Loch in den Bauch, aber tatsächlich stehen wir halt nur auf den Schultern von Giganten, wie man im englischen Sprachraum treffend formuliert.

int hochdrei_1(int x) {  // x ist eine Kopie von b
  int y = x * x * x;
  x = 0;                 // diese Zeile ist sinnlos, da x am Ende der Funktion zerstört wird
  return y;
}

int hochdrei_2(int &x) {  // x ist eine Referenz auf b, keine Kopie
  int y = x * x * x;
  x = 0;                  // dies verändert auch b
  return y;
}

void hochdrei_3(int &x, int &y) {  // x und y sind Referenzen und verändern auch b und c
  y = x * x * x;                   // dies verändert auch c
  x = x * x;                       // dies verändert auch b
}

void hochdrei_4(int *x, int *y) {  // x und y sind Referenzen und verändern auch b und c
  *x = random(15, 25);             // dies verändert auch b
  *y = random(100,200);            // dies verändert auch c
}

void setup() {
  Serial.begin(115200);
  Serial.println("Anfang");
  int b = 3;
  int c = hochdrei_1(b);
  Serial.print("hochdrei_1\t b; ");
  Serial.print(b);
  Serial.print("\tc: ");
  Serial.println(c);

  b = 3;
  c = hochdrei_2(b);
  Serial.print("hochdrei_2\t b: ");
  Serial.print(b);
  Serial.print("\tc: ");
  Serial.println(c);

  b = 3;
  hochdrei_3(b, c);
  Serial.print("hochdrei_3\t b: ");
  Serial.print(b);
  Serial.print("\tc: ");
  Serial.println(c);

  b = 0;  // damit man sieht, dass sich was ändert
  c = 0;
  hochdrei_4(&b, &c);
  Serial.print("hochdrei_4\t b: ");
  Serial.print(b);
  Serial.print("\tc: ");
  Serial.println(c);
}

void loop() {}

Ich habe hochdrei_4 ergänzt, was Deinem Beispiel entspricht. Ich finde das zu kompliziert, probiere mal

bmp085_read_temperature_and_pressure(temperature,pressure);
...
void bmp085_read_temperature_and_pressure(int &temperature, long &pressure) {
  ...
  temperature = (b5 + 8) >> 4;
  ...
  pressure = ...
  ...
}

Viel Spaß beim Fliegen :slight_smile:

combie:
Das ist C++!
Auch dein Beispiel.
Der Beweis: Es wird durch einen C++ Kompiler genudelt.

Ich sehe C als eine Teilmenge recht große Schnittmenge von C++ an. Beweis: Es würde auch der C-Kompiler verstehen.

EDIT: "Teilmenge" in "recht große Schnittmenge" geändert, siehe #29.

Ich tue mich hier richtig schwer, mit dem Begriff Teilmenge.

Gerade auch weil er impliziert:

Lerne erst C, dann haste auch die C++ Grundlagen auf dem Schirm.

Meine Lernempfehlung steht dem eigentlich diamentral entgegen.

Lerne erst die C++ Features/Prinzipien kennen und damit umgehen, dann lernste viele der C Grundlagen automatisch mit.

Ich sehe C als eine Teilmenge von C++ an. Beweis: Es würde auch der C-Kompiler verstehen.

Gegenbeweis: Ein C++ Compiler versteht nicht jeden C Code.

Ja, es gibt große Gemeinsamkeiten.
Denn C++ wurde aus C heraus entwickelt.
Aber C hat sich (recht) unabhängig von C++ weiter entwickelt.
Kein Mensch, der noch alle Streusel auf dem Kuchen hat, will sich heute noch mit dem alten K&R C beschäftigen. Es sei denn er ist EDV-Historiker, für den machts vielleicht Sinn.

Vergleich:
Martin und Lisa haben die gleiche Mama, welche auch Lisa heißt.
Aber das heißt nicht, dass das Kind Lisa eine Teilmenge von Martin ist.
Oder die Mutter Lisa, eine Teilmenge von Martin.

Lisa, Lisa und Martin haben auch Gemeinsamkeiten.
z.B. große Teile der Genetik

Ich versuche das pragmatisch zu sehen, um nicht den (aus meiner Sicht) falschen Begriff Teilmenge zu verwenden.
Meine Empfehlung: Schnittmenge!
(Wenn man denn das Verwandschaftsverhältnis unbedingt benennen will)

C und C++ haben eine recht große Schnittmenge, aus der gemeinsamen Historie bedingt.

Agiert man nur innerhalb der Schnittmenge, dann ist es egal, ob man ein ein Programm*.c nennt und durch einen C Kompiler schickt, oder *.cpp und es dem C++ Kompiler in den Rachen wirft.

Möchte man C und C++ Kompilate miteinander verschmelzen, wirds dann schon "schwieriger"
A. C++ Namemangeling
B. unsichtbarer/impliziter Parameter in der (Methoden) Aufrufkonvention

Gegenbeweis: Ein C++ Compiler versteht nicht jeden C Code

combie hat zwar wie meistens recht, ist aber mal wieder eher verwirrend, fürchte ich.

Ein C++ Compiler versteht "Fast" jeden C-Code.

Es gibt ein paar merkwürdige zulässige C-Konstrukte, die als Fehler in C++ zählen.
Moderne C++ Compiler meckern Sachen an, die ein alter C Compiler durchgehen lässt.

Wobei fraglich ist, ob das Ergebnis tatsächlich so gewollt war. Selbst wenn, kann man sowas (auch in C) immer so schreiben, dass es ein C++ Compiler (und evtl. auch Menschen) verstehen.

Man kann übrigens Sachen, die aus Kompatibilitätsgründen "nur Warnungen" sind, freiwillig als Fehler behandeln lassen.

Anstatt sich immer an solchen Kleinigkeiten hochzuziehen und und in Besserwisserei abzudriften könnte man den "Das ist C" Kommentar auch so verstehen wie er gemeint war: das die Zeiger-Schreibweise aus C kommt und Referenzen erst in C++ eingeführt wurden. Und dass man in moderndem Code wenn möglich Referenzen statt Zeiger verwenden sollte

combie:
C und C++ haben eine recht große Schnittmenge, aus der gemeinsamen Historie bedingt.

Aus der Nähe betrachtet ändere ich meine "Teilmenge" gerne in eine "recht große Schnittmenge".