Hallo zusammen,
Ich versuche gerade die Werte in einem Array, bzw. drei Arrays, um
jeweils eine Index-Stelle weiter zu schieben.
Soll heißen, ich schreibe in den Index 0 bei jedem Durchlaufes des
Programmes irgendwas hinein und dann sollen die alten Werte jeweils um
einen Platz weiter geschrieben werden. Der Wert, der hinten quasi raus
fällt ist egal.
Das Array hat 42 index-Stellen.
momentan versuche ich das so:
1
//Schieberegister weiter schieben
2
for (int i=41; i<1; i--){
3
reihe_rot [i] = reihe_rot [i-1];
4
reihe_gruen [i] = reihe_gruen [i-1];
5
reihe_blau [i] = reihe_blau [i-1];
6
}
Könnt ihr mir sagen, warum das nicht funktioniert?
Gruß
Stefan
Stefan H. schrieb:> for (int i=41; i<1; i--){
Du setzt i auf 41 und fragst dann ob es kleiner 1 ist. Das ist nicht der
Fall. Benutze size_t für Array Indices, nicht int.
IUnknown schrieb:> i<1> ist die falsche Laufbedingung> versuch mal lieber:> i>0> oder noch kürzer, da alles != 0 als wahr angesehen wird:> i
Mann mann mann... Kopf gegen Wand Moment... Danke :D
Es ist zu spät, ich sollte eher schlafen... Danke, jetzt funktioniert es
:)
Stefan H. schrieb:> Öhm okay, was bringt das für Vorteile?
Auf manchen Plattformen wie AMD64 reicht int nicht aus für die mögliche
Größe von Arrays. Außerdem ist es sinnlos einen vorzeichenbehafteten
Integer für etwas zu nehmen, was nie negativ wird.
Immer int zu nehmen macht man in Java, aber nicht C oder C++ :)
Dr. Sommer schrieb:> Stefan H. schrieb:>> Öhm okay, was bringt das für Vorteile?>> Auf manchen Plattformen wie AMD64 reicht int nicht aus für die mögliche> Größe von Arrays. Außerdem ist es sinnlos einen vorzeichenbehafteten> Integer für etwas zu nehmen, was nie negativ wird.>> Immer int zu nehmen macht man in Java, aber nicht C oder C++ :)
Ein ganz klares "kommt drauf an". size_t scheint erst einmal die
logische wahl im C/C++ Kontext zu sein, allerdings sind
vorzeichenbehaftete Indizes effizienter umgesetzt (in Hardware).
Moin,
w're es nicht besser, nur den Schreibezeiger "rotieren" zu lassen
anstatt immer alle Daten unnötig in der Gegend umzukopieren?
Also wenn Daten reinkommen einfach die nächste Stelle im Array
beschreiben und wenn das Ende erreicht ist, einfach von vorne wieder
anfangen. Gibt das gleiche Verhalten nach außen und du musst nicht immer
alle Werte umkopieren.
Das selbe gilt dann natürlich auch für den Lesezeiger.
Keiner N. schrieb:> w're es nicht besser, nur den Schreibezeiger "rotieren" zu lassen> anstatt immer alle Daten unnötig in der Gegend umzukopieren?
Das hab ich mir auch gesagt. Würde hier auch nur den entsprechenden
Schreibzeiger rotieren lassen statt immer das komplette Array
umzukopieren.
Dr. Sommer schrieb:> Stefan H. schrieb:>> for (int i=41; i<1; i--){>> Du setzt i auf 41 und fragst dann ob es kleiner 1 ist. Das ist nicht der> Fall. Benutze size_t für Array Indices, nicht int.
Auch das nicht, sondern C::size_type (C ist der Typ des Containers). Das
ist zwar bei der stdlibc++ immer size_t, da es aber hier um µC geht, hat
man es oft nicht mit der stdlibc++ zu tun, sondern mit speziell
adaptierten Varianten. Da könnte C::size_type auch z.B. ein uint8_t oder
uint16_t sein.
Danke schon mal für eure Antworten :)
Ich bin noch relativ neu in der ganzen Geschichte, daher jetzt mal eine
dumme Frage:
Was meint ihr mit Lesezeiger und Schreibezeiger rotieren lassen?
Ich habe nur einen kleinen Ausschnitt aus meiner Funktion gepostet, ich
könnte später auch noch mal den kompletten Ausschnitt rein stellen. (hab
ich gerade nicht da)
Ich hatte hier :
https://www.mikrocontroller.net/articles/Plattformunabh%C3%A4ngige_Programmierung_in_C
gelesen, dass int den Vorteil bietet, dass es das Format ist, welches
der prozessor am schnellsten bearbeiten kann. Daher hab ich immer int
genommen.
Ist das nicht so, bzw. hab ich das falsch vestanden?
Dr. Sommer schrieb:> eicht int nicht aus für die mögliche> Größe von Arrays.
also unsigned int? bzw gibt es dann einen Unterschied zu unit16_t?
Gruß
Stefan
Stefan H. schrieb:> also unsigned int?
Reicht ggf. auch nicht. Auf AMD64 können Arrays 2^64 Elemente enthalten,
aber (unsigned) int ist typischerweise nur 32bit groß, kann also nur
2^32 Elemente adressieren.
Stefan H. schrieb:> bzw gibt es dann einen Unterschied zu unit16_t?
uint16_t ist was völlig anderes, eben nur 16 bit groß. Ist zu klein für
Arrays auf x86 und AMD64, und ARM, und eigentlich nur ausreichend auf
AVR.
Am Einfachsten ist es immer size_t zu nehmen, das funktioniert immer.
Einen anderen Typ sollte man nur nehmen wenn man sich genau überlegt hat
ob er immer ausreicht.
Stefan H. schrieb:> Was meint ihr mit Lesezeiger und Schreibezeiger rotieren lassen?
Such mal nach FIFO...
Wilhelm M. schrieb:> da es aber hier um µC geht, hat> man es oft nicht mit der stdlibc++ zu tun, sondern mit speziell> adaptierten Varianten.
Kennst du eine Bibliothek bei der das so ist? Und hier geht es um
Arrays, nicht Container.
Dr. Sommer schrieb:> Wilhelm M. schrieb:>> da es aber hier um µC geht, hat>> man es oft nicht mit der stdlibc++ zu tun, sondern mit speziell>> adaptierten Varianten.> Kennst du eine Bibliothek bei der das so ist?
Ja, meine eigene ;-)
Im Ernst: die Väter der stdlibc++ haben sich schon etwas dabei gedacht.
Es handelt sich um eine Art statisches Reflection-API. Der Container
informiert den generischen Code über den size_type. Dadurch ist es
möglich eigene Container zu schreiben (so wie bei meiner Variante) mit
angepasstem size_type. Und dann funktioniert der Code immer richtig
und(!) optimal.
Man ist i.Ü. gut beraten, dieses statische Reflection-API für eigene
Container einzuhalten, damit dann auch die Algorithmen wieder so
funktionieren wie sie sollen.
> Und hier geht es um> Arrays, nicht Container.
Genau, std::array könnte man vermuten ... ich nichts con C-Style-Arrays
gelesen.
Stefan H. schrieb:> Ja gut, das ist dann wohl ein Missverständniss :) Es geht bei mir ja> explizit um einen AVR.
Da kannste trotzdem size_t nehmen, das ist da das gleiche wie uint16_t.
Dafür macht der Code keine Probleme, solltest du ihn jemals z.B. auf
Cortex-M portieren...
Wilhelm M. schrieb:> Man ist i.Ü. gut beraten, dieses statische Reflection-API für eigene> Container einzuhalten,
Schon, aber verschiedene Index-Typen für verschiedene Container zu
nutzen führt schnell zu einem ziemlichen Chaos, weil so ein Index ja oft
auch ausgetauscht werden muss. Da ist es einfacher immer size_t zu
nehmen und das nur zu optimieren wenn das Programm tatsächlich deswegen
zu langsam ist (eh eher unwahrscheinlich).
Dr. Sommer schrieb:> Wilhelm M. schrieb:>> Man ist i.Ü. gut beraten, dieses statische Reflection-API für eigene>> Container einzuhalten,> Schon, aber verschiedene Index-Typen für verschiedene Container zu> nutzen führt schnell zu einem ziemlichen Chaos, weil so ein Index ja oft> auch ausgetauscht werden muss.
Ganz und gar nicht: es macht ggf. das Problem sichtbar! Vor allem, wenn
man es so gestaltet, dass die Index-Typen nicht implizit, sondern nur
explizit ineinander konvertierbar sind.
Denn es macht ja nun wenig Sinn, für einen Container, der nur 256
Elemente fassen kann, einen Index-Typ mit 16-Bit zu verwenden.
Wie würdest du denn dann z.B. folgenden (recht sinnfreien) Algorithmus
so bauen, dass er auch dann noch funktioniert, wenn die beiden Container
unterschiedliche Index-Typen haben?
Erster Q-n-D-Ansatz:
hier würde ich pessimistisch vorgehen: das Ganze macht nur Sinn, wenn
die generierten Indizes innerhalb der durch die Indextypen vorgegeben
Wertebereiche liegen.
Wilhelm M. schrieb:> <std::numeric_limits<T1>::max() <= std::numeric_limits<T2>::max()
Das klappt eventuell nicht wenn es keinen Typ gibt der groß genug ist um
die Bereiche von T1 und T2 abzudecken.
Wilhelm M. schrieb:> void test (C1& c1, const C2& c2, size_t off1, size_t off2) {
Hier doch wieder size_t?
Wilhelm M. schrieb:> size_t count = std::min<size_t> (c1.size () - off1, c2.size () -> off2);
Der Vergleich soll dann doch auf size_t durchgeführt werden? Ist size_t
nicht eventuell zu groß für "count"?
Wilhelm M. schrieb:> for (index_type i = 0; i < count; ++i) {
Wenn index_type kleiner als size_t ist, macht man hier dann ständig
unnötige Vergleiche via size_t
Wilhelm M. schrieb:> std::cout << "Kopiere Element " << int(i) << std::endl;
Was wenn "i" größer als "int" ist?
Wilhelm M. schrieb:> c1 [index1_type{i+off1}] = c2[index2_type{i+off2}];
Das gibt ggf. Compiler-Warnungen wegen Integer Promotion
Stefan H. schrieb:> Ich bin noch relativ neu in der ganzen Geschichte, daher jetzt mal eine> dumme Frage:> Was meint ihr mit Lesezeiger und Schreibezeiger rotieren lassen?
Dann wird das ein Ringpuffer oder FIFO. Lies dir das mal durch :
https://www.mikrocontroller.net/articles/FIFO
Mein Post war auch mehr als Ideengeber gedacht als fertiger Code ....
Dr. Sommer schrieb:> Wilhelm M. schrieb:>> <std::numeric_limits<T1>::max() <= std::numeric_limits<T2>::max()>> Das klappt eventuell nicht wenn es keinen Typ gibt der groß genug ist um> die Bereiche von T1 und T2 abzudecken.
s.u. im Code
>> Wilhelm M. schrieb:>> void test (C1& c1, const C2& c2, size_t off1, size_t off2) {> Hier doch wieder size_t?
Das war nur Nachlässigkeit (s.u.)
>> Wilhelm M. schrieb:>> size_t count = std::min<size_t> (c1.size () - off1, c2.size () ->> off2);> Der Vergleich soll dann doch auf size_t durchgeführt werden? Ist size_t> nicht eventuell zu groß für "count"?
s.u.
>> Wilhelm M. schrieb:>> for (index_type i = 0; i < count; ++i) {
s.u.
>> Wenn index_type kleiner als size_t ist, macht man hier dann ständig> unnötige Vergleiche via size_t>> Wilhelm M. schrieb:>> std::cout << "Kopiere Element " << int(i) << std::endl;> Was wenn "i" größer als "int" ist?
War nur ggf. wegen uint8_t als index_type, dass würde sonst als char
ausgegeben, s.u.
>> Wilhelm M. schrieb:>> c1 [index1_type{i+off1}] = c2[index2_type{i+off2}];> Das gibt ggf. Compiler-Warnungen wegen Integer Promotion
besser gesagt wegen narrowing. Auch dazu s.u.
std::cout<<"Kopiere Element "<<std::to_string(i)<<std::endl;
43
c1[index1_type(i+off1)]=c2[index2_type(i+off2)];
44
}
45
}
Einige Laufzeit-Zusicherungen sind hier nur Testing-Comments. Ist auch
alles nur schnell hingeschrieben, keine Ahnung, ob ich an alles gedacht
habe ;-)
Stefan H. schrieb:> Danke schon mal für eure Antworten :)> Ich bin noch relativ neu in der ganzen Geschichte, daher jetzt mal eine> dumme Frage:> Was meint ihr mit Lesezeiger und Schreibezeiger rotieren lassen?> ...
Eigentlich willst du einen Ringpuffer aufbauen, dazu gibt es hier ein
schönes Beispiel mit Lösungsansätzen für verschiedene Sprachen, u.a. C:
https://www.programmieraufgaben.ch/aufgabe/ringpuffer-mit-arrays/yui8z5du
http://www.cplusplus.com/reference/stl/
Container adaptors:
stack
LIFO stack (class template )
queue
FIFO queue (class template )
priority_queue
Priority queue (class template )
Wieso nicht einfach einen fertigen Container dafür benutzen?
M. K. schrieb:> Eigentlich willst du einen Ringpuffer aufbauen, dazu gibt es hier ein> schönes Beispiel mit Lösungsansätzen für verschiedene Sprachen, u.a. C:>> https://www.programmieraufgaben.ch/aufgabe/ringpuffer-mit-arrays/yui8z5du
Das soll doch ein schlechter Scherz sein, oder?
Egon N. schrieb:> http://www.cplusplus.com/reference/stl/> Container adaptors:>> stack> LIFO stack (class template )>> queue> FIFO queue (class template )>> priority_queue> Priority queue (class template )>>> Wieso nicht einfach einen fertigen Container dafür benutzen?
Es ist gut, wenn man die Threads auch mal liest: es geht dem TO um AVR,
da gibt es keine fertige stdlibc++ und ich glaube auch nicht, dass der
TO sie sich selbst schreibt ;-)
Wilhelm M. schrieb:> Es ist gut, wenn man die Threads auch mal liest: es geht dem TO um AVR,> da gibt es keine fertige stdlibc++ und ich glaube auch nicht, dass der> TO sie sich selbst schreibt ;-)
Man kann sich durchaus von der Bibliothek inspirieren lassen. Man muss
nicht die ganze Lib implementieren, aber die Ausführungen sind in der
Regel sehr gut.
Zudem kann man es als Anreiz verstehen sich mal Cortex-M anzuschauen,
denn da gibt es eine stdlib++.