Hallo,
anbei mal ein Ausschnitt aus einem Code. Die Funktion soll wohl im
großen und ganzen sich um serielle Daten kümmern.
An den Stellen wo ein Kommentar ist, verstehe ich den Sinn nicht ganz,
kann mir vielleicht jemand auf die Sprünge helfen und evtl. verstehen
was der Entwickler dieses Codes damit bezwecken wollte..
Der Code kopiert Daten vom Flash in den RAM (genauer: Variable auf dem
Stack) um die besser verarbeiten zu können.
Das mit den Pointern (und wann was scheibbar ist und wo const stehen
muss) übst Du besser nochmal.
Ach ja: Solche Klimmzüge sind nur für AVR nötig - weil AVR eine Havard
Architektur ist, C aber eher für von-Neumann Architekturen gedacht ist.
Allerdings müsste ich auch z.B. auf Cortex-M3 Flash Daten erstmal ins
RAM kopieren wenn ich sie ändern will.
Was hier passiert:
- p zeigt auf das Input-struct
- dann wird tab_ptr auf das lokale struct "jt" umgemapt
- dann wird das Input-struct in das lokale struct kopiert.
const ist übrigens nicht tab_ptr selber, sondern der Speicherbereich,
auf den er zeigt.
Das hätte man auch einfacher haben können:
1
memcpy(&jt,tab_ptr,sizeof(jt));
Und das im Rest der Funktion mit jt statt mit tab_ptr referenzieren. Das
wäre auch deswegen sauberer, weil tab_ptr als ein Pointer auf konstante
Daten deklariert ist, und diesen Datentyp behält er auch dam dem
Ummappen auf "jt".
Nop schrieb:> Was hier passiert:> const ist übrigens nicht tab_ptr selber, sondern der Speicherbereich,> auf den er zeigt.
Ok. Das heißt den Zeiger ansich kann ich verändern nur den
Speicherbereich, sollte ich nicht verändern?
Was genau ist PGM_P für ein Macro?
Einfach ein Zeiger vom Typ char?
Je nachdem, welchen Typ sio_job_tabelle.pos hat, fällt der letzte Cast
auch weg.
Anstatt p könnte man auch tab_ptr verwenden, um durch den Speicher zu
laufen, aber das ist Geschmackssache.
Unter Verwendung von __flash kann man's auch so schreiben:
was es für den Fall .typ = 0 schneller mach da nicht der gesamte Struct
gelesen wird.
Schließlich kann man sio_job_tabelle per Typedef definieren, so dass das
lästige "struct" wegfällt:
Marvin W. schrieb:> Nop schrieb:>> Was hier passiert:>>>> - p zeigt auf das Input-struct
Nur anfangs, p wird in der while-Schleife verändert.
>> Wieso wird es auf char gecastet?
Hack und unnötig, siehe mein Beispielcode.
Man kann zwar alles als char* abwickeln, aber p zeigt immer auf ein
struct sio_job_tabelle das nur gelesen wird, d.h. der natürliche Typ für
p wäre
const struct sio_job_tabelle* oder eben const __flash struct
sio_job_tabelle*.
Mutluit M. schrieb:> Kannst noch weiter kürzen:>> Den> memcpy_P (&jt, p, sizeof (struct sio_job_tabelle));> kann man durch die folgende Zuweisung ersetzen:> jt = *p;>> :-)
Sicher? Kopiert die Funktion mehrere Bytes?
Marvin W. schrieb:> Was genau ist PGM_P für ein Macro?> Einfach ein Zeiger vom Typ char?
Das siehst du indem du dessen Definition dir anschaust
(entweder weiter oben im code oder in einem include-file...)
Mutluit M. schrieb:> Marvin W. schrieb:> Was genau ist PGM_P für ein Macro?> Einfach ein Zeiger vom Typ char?>> Das siehst du indem du dessen Definition dir anschaust> (entweder weiter oben im code oder in einem include-file...)
Habe ich.. Dahinter verbirgt sich einfach nur "PGM_P". Ich war der
Annahme das es irgendwas mit dem lesen aus dem flash zu tun hat..
Marvin W. schrieb:> Mutluit M. schrieb:>> Marvin W. schrieb:>> Was genau ist PGM_P für ein Macro?>> Einfach ein Zeiger vom Typ char?>>>> Das siehst du indem du dessen Definition dir anschaust>> (entweder weiter oben im code oder in einem include-file...)>> Habe ich.. Dahinter verbirgt sich einfach nur "PGM_P". Ich war der> Annahme das es irgendwas mit dem lesen aus dem flash zu tun hat..
PGM_P müsste ein char* sein.
Marvin W. schrieb:> Mutluit M. schrieb:>> Kannst noch weiter kürzen:>>>> Den>> memcpy_P (&jt, p, sizeof (struct sio_job_tabelle));>> kann man durch die folgende Zuweisung ersetzen:>> jt = *p;>>>> :-)>> Sicher? Kopiert die Funktion mehrere Bytes?
So kannst du ganze Strukturen kopieren, egal wie gross :-)
Wollte ich eigentlich schreiben :)).
Was ist mit..?
Mutluit M. schrieb:
Kannst noch weiter kürzen:
Den
memcpy_P (&jt, p, sizeof (struct sio_job_tabelle));
kann man durch die folgende Zuweisung ersetzen:
jt = *p;
:-)
Sicher? Kopiert die Funktion mehrere Bytes?
Mutluit M. schrieb:> Marvin W. schrieb:> Mutluit M. schrieb:> Kannst noch weiter kürzen:>> Den> memcpy_P (&jt, p, sizeof (struct sio_job_tabelle));> kann man durch die folgende Zuweisung ersetzen:> jt = *p;>> :-)>> Sicher? Kopiert die Funktion mehrere Bytes?>> So kannst du ganze Strukturen kopieren, egal wie gross :-)
Wieso hat man dann die Funktion gewählt? Das ist doch deutlich
performanter deine Idee...
Marvin W. schrieb:>> Den>> memcpy_P (&jt, p, sizeof (struct sio_job_tabelle));>> kann man durch die folgende Zuweisung ersetzen:>> jt = *p;>>>> :-)>>>> Sicher? Kopiert die Funktion mehrere Bytes?>>>> So kannst du ganze Strukturen kopieren, egal wie gross :-)>> Wieso hat man dann die Funktion gewählt? Das ist doch deutlich> performanter deine Idee...
Du musst wissen: es gibt viele dumme Programmierer da draussen... :-)
Man müsste sich das Innere von memcpy_P() anschauen; es scheint etwas
mehr zu machen als nur kopieren...
Die Zuweisung würde sich empfehlen anstelle von memcpy().
Mutluit M. schrieb:> Man müsste sich das Innere von memcpy_P() anschauen; es scheint etwas> mehr zu machen als nur kopieren...> Die Zuweisung würde sich empfehlen anstelle von memcpy().
Wieso?
Jan H. schrieb:> Mutluit M. schrieb:>> Man müsste sich das Innere von memcpy_P() anschauen; es scheint etwas>> mehr zu machen als nur kopieren...>> Die Zuweisung würde sich empfehlen anstelle von memcpy().>> Wieso?
Was meinst du mit wieso?
Nennt sich Objekt-Zuweisung, also wie in Mathe: A = B usw...
Mutluit M. schrieb:> Jan H. schrieb:>> Wieso Du es empfehlen würdest...>> Ist doch das naheliegendste. :-)> Oder etwa nicht?
Ich kenne die Funktion jetzt nicht.
Würde jedoch gerne wissen, wieso und was diese Funktion anders macht.
Ich glaube kaum das sie nur diese Zuweisung erledigt. Dafür bräuchte man
nicht so viele Parameter übergeben?!
Jan H. schrieb:> Mutluit M. schrieb:>> Jan H. schrieb:>>> Wieso Du es empfehlen würdest...>>>> Ist doch das naheliegendste. :-)>> Oder etwa nicht?>> Ich kenne die Funktion jetzt nicht.> Würde jedoch gerne wissen, wieso und was diese Funktion anders macht.> Ich glaube kaum das sie nur diese Zuweisung erledigt. Dafür bräuchte man> nicht so viele Parameter übergeben?!
Deine Neugier ist gut.
Aber dann befriedige deine Neugier doch einfach indem du nachschaust.
Den Code hast du ja von irgendwoher. Da müsste auch der Rest sein...
Ich meine, der Marvin müsste den Rest des Codes haben..
Jan H. schrieb:> Dann gehe ich mal davon aus, dass du es nicht weißt?
Die besagte Funktion hat die selbe Signatur, also die selben Parameter,
wie das standard memcpy():
memcpy(ziel, quelle, laenge)
Mutluit M. schrieb:> Jan H. schrieb:>> Dann gehe ich mal davon aus, dass du es nicht weißt?>> Die besagte Funktion hat die selbe Signatur, also die selben Parameter,> wie das standard memcpy():>> memcpy(ziel, quelle, laenge)
Du meintest weiter oben, die Zuweisung würde alleine reichen.. Jetzt
schreibst Du was von memcpy.. Was denn nu?
Jan H. schrieb:> Mutluit M. schrieb:>> Jan H. schrieb:>>> Dann gehe ich mal davon aus, dass du es nicht weißt?>>>> Die besagte Funktion hat die selbe Signatur, also die selben Parameter,>> wie das standard memcpy():>>>> memcpy(ziel, quelle, laenge)>> Du meintest weiter oben, die Zuweisung würde alleine reichen.. Jetzt> schreibst Du was von memcpy.. Was denn nu?
Ich glaube du scheinst durcheinandergekommen zu sein.
Die besagte Funktion hat die selbe Signatur, also selbe Parameter und
Rückgabetyp, wie das standard memcpy():
memcpy(ziel, quelle, laenge)
Der anfänglich gepostete Code-Ausschnitt gehört doch nicht zum
Standardumfang eines Compilers. Das ist vielmehr eine externe Library
oder einfach eine Anwendung. Da ich den Code nicht kenne, kann ich auch
nicht sagen was in memcpy_P() passiert.
Vlt. hast du nicht gemerkt dass es memcpy() gibt und memcpy_P().
Das erste ist in der Standardlibrary jedes C/C++-Compilers. Das
memcpy_P() ist etwas selbstgeschriebenes (Code wurde nicht gepostet).
Statt memcpy() kann man die Zuweisung benutzen wenn es sich um nur ein
Element handelt (also kein Array).
Ich glaube eher weniger das diese Funktion selbst geschrieben wurde, sie
ist Teil vom AVR siehe hier ->
https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html
Für ein Element hätte ich es noch verstanden. Weiter oben wurde aber von
der ganzen Struktur gesprochen bzw. geschrieben.
Marvin W. schrieb:> Wieso hat man dann die Funktion gewählt?
Der Code wurde für avr-gcc älter alt v4.7 geschrieben oder der Autor war
auf dem Wissensstand: __flash wurde erst in v4.7 eingeführt, während es
memcpy_P als Teil der avr-libc seit Anbeginn der Zeit gibt.
Das Pointer-Target von p braucht diesen Qualifier um aus dem Flash zu
lesen, ansonsten liest jt = *p aus dem RAM.
> Das ist doch deutlich performanter deine Idee...
Die Performance ist i.W. gleich. memcpy_P macht einen Funktionsaufruf;
die Struct-Zuweisung wird von avr-gcc inline expandiert.
Wenn man kleinen Code will, kann memcpy_P besser sein bei
Mehrfachverwendung. Der Overhead durch den Funktionsaufruf hält sich in
Grenzen: weniger als 10 Ticks.
Jan H. schrieb:> Ich glaube eher weniger das diese Funktion selbst geschrieben wurde, sie> ist Teil vom AVR siehe hier ->> https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html
Du musst wissen: C und C++ haben jeweils eine sog. Standardbibliothek.
Die o.g. Funktion memcpy_P() ist nicht Teil des Sprach-Standards.
Folglich muss es etwas anderes sein, also Teil einer anderen Bibliothek
usw.
> Für ein Element hätte ich es noch verstanden. Weiter oben wurde aber von> der ganzen Struktur gesprochen bzw. geschrieben.
Du muss Objekt-weise denken: eine Struktur ist ein Objekt (bzw. Klasse),
ebenso eine int-Variable usw...
Mutluit M. schrieb:> Jan H. schrieb:>> Ich glaube eher weniger das diese Funktion selbst geschrieben wurde, sie>> ist Teil vom AVR siehe hier ->>> https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html> Du muss Objekt-weise denken: eine Struktur ist ein Objekt (bzw. Klasse),> ebenso eine int-Variable usw...
Das habe ich ehrlich gesagt noch nie ausprobiert. Damit wird also in C
eine Struktur kopiert? Dann braucht man diese Funktion ja wirklich
nicht.
Jan H. schrieb:> Mutluit M. schrieb:>> Jan H. schrieb:>>> Ich glaube eher weniger das diese Funktion selbst geschrieben wurde, sie>>> ist Teil vom AVR siehe hier ->>>> https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html>> Du muss Objekt-weise denken: eine Struktur ist ein Objekt (bzw. Klasse),>> ebenso eine int-Variable usw...>> Das habe ich ehrlich gesagt noch nie ausprobiert. Damit wird also in C> eine Struktur kopiert? Dann braucht man diese Funktion ja wirklich> nicht.
Wie gesagt ist es keine Standard-Funktion, ebensowenig wie __flash
Standard ist. Und ohne __flash funktioniert so eine Zuweisung eben
nicht.
Also Leute, C sollte man wirklich nicht auf so einem AVR lernen! :-)
Lernt es auf dem normalen PC bzw. Laptop.
C ist im Grunde eine sehr einfach zu lernende Sprache.
Es ist so "rein" wie Mathematik.
Mutluit M. schrieb:> Also Leute, C sollte man wirklich nicht auf so einem AVR lernen! :-)> Lernt es auf dem normalen PC bzw. Laptop.>> C ist im Grunde eine sehr einfach zu lernende Sprache.> Es ist so "rein" wie Mathematik.
Ich nehme es mir mal zu Herzen.
Mutluit M. schrieb:> C ist im Grunde eine sehr einfach zu lernende Sprache.> Es ist so "rein" wie Mathematik.
Dann kennst du C höchstens oberflächlich.
nvidia schrieb:> Mutluit M. schrieb:>> C ist im Grunde eine sehr einfach zu lernende Sprache.>> Es ist so "rein" wie Mathematik.>> Dann kennst du C höchstens oberflächlich.
Wieso? Klappt's bei dir nicht so wie es soll? :-)
Mutluit M. schrieb:> nvidia schrieb:>> Mutluit M. schrieb:>>> C ist im Grunde eine sehr einfach zu lernende Sprache.>>> Es ist so "rein" wie Mathematik.>>>> Dann kennst du C höchstens oberflächlich.>> Wieso? Klappt's bei dir nicht so wie es soll? :-)
Ne, im Gegensatz zu den Meisten habe ich mir den C-Standard mal
angeguckt und darf bei dem meisten zu findenem Code irgendwelches
schlecht definiertes Verhalten entdecken.
Die, die sich für C interessieren sollten sich erstmal das in Ruhe
reinziehen um ein Überblick zu bekommen und sich auch über die Historie
informieren:
https://de.wikipedia.org/wiki/C_(Programmiersprache)
Da findet man auch diesen zutreffenden Satz:
"Abgesehen vom Mikrocontrollerbereich, wo eigene Dialekte existieren,
sind die meisten aktuellen PC-/Server-Implementierungen eng an den
Standard angelehnt [...]"
nvidia schrieb:> Mutluit M. schrieb:>> nvidia schrieb:>>> Mutluit M. schrieb:>>>> C ist im Grunde eine sehr einfach zu lernende Sprache.>>>> Es ist so "rein" wie Mathematik.>>>>>> Dann kennst du C höchstens oberflächlich.>>>> Wieso? Klappt's bei dir nicht so wie es soll? :-)>> Ne, im Gegensatz zu den Meisten habe ich mir den C-Standard mal> angeguckt und darf bei dem meisten zu findenem Code irgendwelches> schlecht definiertes Verhalten entdecken.
Kannst du das nochmal in Deutsch schreiben, damit man es versteht? :-)
Mutluit M. schrieb:> nvidia schrieb:>> Mutluit M. schrieb:>>> nvidia schrieb:>>>> Mutluit M. schrieb:>>>>> C ist im Grunde eine sehr einfach zu lernende Sprache.>>>>> Es ist so "rein" wie Mathematik.>>>>>>>> Dann kennst du C höchstens oberflächlich.>>>>>> Wieso? Klappt's bei dir nicht so wie es soll? :-)>>>> Ne, im Gegensatz zu den Meisten habe ich mir den C-Standard mal>> angeguckt und darf bei dem meisten zu findenem Code irgendwelches>> schlecht definiertes Verhalten entdecken.>> Kannst du das nochmal in Deutsch schreiben, damit man es versteht? :-)
C ist so genial konzipiert, dass es kaum einer schafft, Code zu
schreiben, der voll definiert ist und dabei auch noch garantiert*
funktioniert.
*mal abgesehen von irgendwelchen numerischen Grenzen die in der Praxis
nicht überschritten werden
nvidia schrieb:> Mutluit M. schrieb:>> nvidia schrieb:>>> Mutluit M. schrieb:>>>> nvidia schrieb:>>>>> Mutluit M. schrieb:>>>>>> C ist im Grunde eine sehr einfach zu lernende Sprache.>>>>>> Es ist so "rein" wie Mathematik.>>>>>>>>>> Dann kennst du C höchstens oberflächlich.>>>>>>>> Wieso? Klappt's bei dir nicht so wie es soll? :-)>>>>>> Ne, im Gegensatz zu den Meisten habe ich mir den C-Standard mal>>> angeguckt und darf bei dem meisten zu findenem Code irgendwelches>>> schlecht definiertes Verhalten entdecken.>>>> Kannst du das nochmal in Deutsch schreiben, damit man es versteht? :-)>> C ist so genial konzipiert, dass es kaum einer schafft, Code zu> schreiben, der voll definiert ist und dabei auch noch garantiert*> funktioniert.
Dann mach dich mal schlau über Yacc & Co.:
https://en.wikipedia.org/wiki/Yacc
Die Sprache C ist wie ein Algorithmus in sich geschlossen definiert.
Es wird mit so einem Compiler-Compiler erstellt. Also quasi maschinell
erzeugt.
Mutluit M. schrieb:> Dann mach dich mal schlau über Yacc & Co.:> https://en.wikipedia.org/wiki/Yacc> Die Sprache C ist wie ein Algorithmus in sich geschlossen definiert.> Es wird mit so einem Compiler-Compiler erstellt. Also quasi maschinell> erzeugt.
Sind dir Sachen wie "undefiniertes Verhalten" kein Begriff? Zu viel
getrunken?
nvidia schrieb:> Mutluit M. schrieb:>> Dann mach dich mal schlau über Yacc & Co.:>> https://en.wikipedia.org/wiki/Yacc>> Die Sprache C ist wie ein Algorithmus in sich geschlossen definiert.>> Es wird mit so einem Compiler-Compiler erstellt. Also quasi maschinell>> erzeugt.>> Sind dir Sachen wie "undefiniertes Verhalten" kein Begriff? Zu viel> getrunken?
Ich habe überhaupt keine Probleme mit C oder C++. Im Gegenteil: ist
alles logisch.
Wenn du mit C nicht klar kommst, dann liegt es mit 99.99999%
Wahrscheinlichkeit an dir selbst :-)
Johann L. schrieb:> __flash
nur so am rand ...
der gcc qualifier __flash existiert nur in c und nicht in c++, also kann
z.b. NICHT mit dem arduino framework verwendet werden.
mt
Mutluit M. schrieb:> Statt memcpy() kann man die Zuweisung benutzen wenn es sich um nur ein> Element handelt (also kein Array).
Bei der Zuweisung kann es Probleme geben, wenn die Bereiche Miss-Aligned
sind.
Dirk B. schrieb:> Mutluit M. schrieb:>> Statt memcpy() kann man die Zuweisung benutzen wenn es sich um nur ein>> Element handelt (also kein Array).>> Bei der Zuweisung kann es Probleme geben, wenn die Bereiche Miss-Aligned> sind.
Das kann bei memcpy auch passieren.
Wenn der Bereich nicht aligned ist dann läuft es natürlich langsamer.
Aber in der Praxis unter normalen Bedingungen kann es nicht passieren,
wenn man nicht gerade #pragma pack(1) oder so definiert hat vor den
Variablendefinitionen.
Ansonsten zeige mal ein Beispiel wo es Probleme machen würde.