Datentyp "byte" - kleine Frage dazu

Hallo,

versuche gerade einen funktionierenden Sketch (Thema 24LC64 EEPROM auslesen) nachzuvollziehen. Jetzt steht dort:

i2c_eeprom_write_page(0x50, 0, (byte *)somedata, sizeof(somedata));

Mir ist aber nicht klar, was das * in byte * bedeutet. Habe auch bisher nix dazu finden können. Kann mir das mal bitte jemand erklären?

Thx

Das ist ein Cast auf einen Pointer/Zeiger auf Byte

Cast: http://de.wikipedia.org/wiki/Typumwandlung

Pointer: http://de.wikipedia.org/wiki/Zeiger_%28Informatik%29 http://www.willemer.de/informatik/cpp/pointer.htm

Du findest da verschiedene Varianten wie: int* data int * data int *data

Persönlich bevorzuge ich den Pointer Operator direkt am Datentyp, aber das sieht man mal so, mal so.

Ok vielen Dank. Das sagt mir jetzt zwar noch nicht so viel, aber ich habe nun genug Hinweise, wo und wie ich mehr darüber finde. Dankeschön. :)

Das ist einfach ein Zeiger auf die Speicher-Adresse wo die Variable steht. Genauer, die erste/niedrigste Adresse des Speicherbereichs.

Der Cast wird gemacht, da auch mal mehr als ein Byte abspeichern willst. Zum Beispiel ein int. Die Variable wird dann durch den Cast als Byte behandelt, da das EEPROM Byte-weise arbeitet. Und sizeof einer int-Variablen ist 2.

Wow,

http://www.willemer.de/informatik/cpp/pointer.htm ist nach meinem Geschmack - eine tolle Erklärung!

Wenn ich das richtig verstanden habe, dann bedeutet das (byte *)somedata dass hier die Speicheradresse von "somedata" von HEX in BYTE konvertiert wird, richtig? Also hier wird die Zeigervariable (auf "somedata") als BYTE-Typ beim Funktionsaufruf übergeben, korrekt?

:blush:

Genauer, die erste/niedrigste Adresse des Speicherbereichs

Oh das ist auch sehr hilfreich! In meinem Beispiel ist “somedata” ein Array. Jetzt kommt Licht ins Dunkel. Dank Euch! :wink:

dass hier die Speicheradresse von "somedata" von HEX in BYTE konvertiert wird, richtig? Also hier wird die Zeigervariable (auf "somedata") als BYTE-Typ beim Funktionsaufruf übergeben, korrekt?

Jein. Hexadezimal ist nur eine Schreibweise. Das ist unabhängig vom Datentyp.

Zeiger sind eigene Datentypen. Der Datentyp des Parameters ist "Zeiger auf Byte". Nicht "Byte". Es wird ein Zeiger auf eine Byte-Variable übergeben. Bzw. die übergebene Variable wird als (Zeiger auf) Byte behandelt auch wenn da eigentlich ein int, long oder float drin steht. Ohne den Cast würde der Compiler wahrscheinlich was in Richtung von "can't convert from int* to byte*" meckern.

P.S.: Wegen Arrays. Array Variablen sind automatisch Pointer auf das erste Element des Arrays. Deshalb braucht man beim Methoden-Aufruf nicht den Adresse-von Operator &

Okay ich muss darüber nachdenken! Es “dämmert” mir, jedoch kann ich das noch nicht ganz “greifen”.

Also hier nochmal Aufruf der Funktion:

i2c_eeprom_write_page(0x50, 0, (byte *)somedata, sizeof(somedata));

Das (byte *)somedata ist ja nun bekannt.

Und hier die erste Funktionszeile:

void i2c_eeprom_write_page( int deviceaddress, unsigned int eeaddresspage, byte* data, byte length )

Warum ist hier nun ein byte* data? Also warum ändert sich hier die Syntax mit den Klammern? “data” ist doch nun die funktionsinterne Variable mit dem Verweis auf den Inhalt des Array “somedata” in Form eines Zeigers auf dessen “Adressbyte”, richtig? Ich habe noch nicht kapiert, wie ich mit diesem Zeiger “umgehe”.

Vielleicht hilft mir das zum “Klick” im Schädel!? :fearful:

Byte weil das EEPROM jedes Byte einzeln schreibt. Du kannst nicht einen 2-Byte Integer auf einmal schreiben. Die Methode teilt das dann auf und schreibt jedes Byte für sich.

So kannst du Arrays beliebiger Datentypen übergeben und der Methode ist egal was das eigentlich ist. Ansonsten bräuchte man für jeden Datentyp eine eigene Methode.

Die Klammern sind in der Methoden-Definition nicht mehr da, weil hier nur eine Variable “Zeiger auf Byte” definiert wird. Beim Aufruf der Methode stellen die Klammern einen Cast auf “Zeiger auf Byte” dar. Die Variable “somedata” (die z.B. ein int* sein kann) wird auf byte* gecastet und in die Variable “data” kopiert. Ohne den Cast würde der Compiler dieses Kopieren nicht zulassen, da die Typen inkompatibel sind (es sei denn “somedata” ist ein Byte-Array).

data" ist doch nun die funktionsinterne Variable mit dem Inhalt der Speicheradresse des Array “somedata” in Form eines Zeigers auf das “Adressbyte”, richtig?

Du meinst wahrscheinlich das richtige, aber “Inhalt der Speicheradresse” ist der Wert der darin abgespeichert ist. Der wird hier eben nicht übergeben. Sondern nur die Adresse selbst. Lass das “mit dem Inhalt der” weg, dann kann man es lassen :slight_smile:

Und ein Zeiger nichts anderes als ein spezieller Integer in dem die Adresse steht. Auf dem Arduino glaube ich 16 Bit.

Wenn ich in Visual C++ das mache:

int data = 5;
int* p_data = &data;

cout << p_data << endl;

…wird das ausgegeben:
0044FF28

Und das:

int data[] = { 1, 2 };
cout << data << endl << &data[1] << endl;

…liefert:
0024FBA4
0024FBA8

int hat auf dem PC 4 Byte. Daher ist die 2. Adresse 4 größer als die erste

Um auf den Inhalt von data zu kommen muss man das schreiben:
cout << *data; //oder *p_data beim ersten Beispiel

Also der Inhalt der Adresse auf die der Pointer verweist. Was bei Arrays das gleiche wie data[0] ist.

:~ Jetzt haben wir uns "überschnitten" mit den Posts (Ich musste nochmal editieren).

Aber änderte genau das, was Du "bemängelst" :D Ich glaube ich hab es schon ganz gut kapiert. (Vielleicht die Syntax der beiden byte * in meinem Beispiel noch nicht so recht) Ich lese im Buch parallel dazu nochmal die Klamotte MSB und LSB - das meintest Du sicherlich mit

Du kannst nicht einen 2-Byte Integer auf einmal schreiben. Die Methode teilt das dann auf und schreibt jedes Byte für sich

Leider hilft mir C oder C++ NOCH nicht weiter, da ich erst kürzlich und bisher nur via Arduino in das Thema Mikrocontroller eingestiegen bin. Ich merke jedoch inzwischen, dass ich auf die "Basics" in C bzw. C++ nicht verzichten möchte. Es bringt ja auch viel Freude! :sweat_smile:

Hab vielen Dank für Deine Mühe - Du hast mir schon sehr geholfen! Klasse, dass es Menschen wie Dich gibt, die Menschen wie mir ihre Zeit schenken ]:D

Habe noch mal was zum Unterschied zwischen "byte* data" und (byte*) editiert. Das erste ist einfach eine Variablen-Definition. Das zweite ist ein Cast.

Mach dir keine Sorgen. Pointer sind anfangs sehr verwirrend und man kann da viele böse Fehler machen.

AAAAAAAAAAH :D

Jetzt hat es wohl geklickt! Du hast das zwar schon vorher geschrieben - aber es ist nicht durchgedrungen! Das byte * ist ein eigener Datentyp! Ja, ja - und der cast (byte *) "castet" bei der Übergabe "somedata" nicht in den Typ Byte, sondern in den Typ byte *, was einem Zeiger entspricht! Und in der Funktion (oder Methode, wie Du es nennst) wird, wie sonst auch üblich, die Variable "data" als Zeiger aufs Array "somedata" deklariert.

So jetzt richtig? :D Egal ;)

Ja :)

Du kannst mal spaßhalber den Cast weglassen. Oder statt einem Array ein einzelnes Byte übergeben. Und dann die Fehlermeldungen anschauen.

Variable "data" als Zeiger aufs Array "somedata"

Wobei Array-Variablen in C/C++ eben schon Zeiger sind! Auch wenn man es an der Syntax nicht sieht. Das ist ein Spezial-Fall. "somedata" ist schon ein Zeiger auf den Datentypen aus dem das Array besteht.

int* data; int data[];

"data" ist in beiden Fällen ein int*

Wenn man es genau nimmt, gibt es Funktionen in C und Methoden in C++. Methoden gehören einer Klasse an (welche es in C nicht gibt). Das ist artet aber hier in Haarspalterei aus und man kann auch beide Wörter synonym verwenden.