ich habe 5 Arrays die ich im Moment noch als Test vor dem (Setup) Mainloop mit berechneten Werten auffülle, teils sind das Bitschieberei oder auch einige For-Schleifen aus den Arduino "Defines". Ich habe mich jetzt gefragt ob das so optimiert wird das es vorweg berechnet wird weil es ja dann Fest ist oder ich das ganze in Makros und Defines umdefinieren muss. Gibt es dazu eine gute Seite die das mit den Makros einigermaßen beschreibt? In den Artikeln die ich hier gefunden habe sind keine Beispiele bzw. Speziell ASM Makros behandelt.
Zeig doch einfach deinen Code. Deine Erzählungen darüber helfen nicht weiter. Oliver
Makros sind Textersetzungen, die vor dem Compilieren angewendet werden. Der GCC hat eine Kommandozeilenoptionen, mit dem du den modifizierten Quelltext ausgeben kannst. Wie gut der Compiler deinen Code optimiert, hängt ganz stark vom Compiler, seinen Optionen und natürlich dem aktuellen Quelltext ab. Alle drei Infos solltest du ganz schnell nachreichen, damit das hier nicht zu einer endlosen Diskussion ohne Praxisbezug ausartet, wo sich jeder einbildet, besser zu wissen, was du gerade machst oder brauchst.
Philipp K. schrieb: > Ich habe mich jetzt gefragt ob das so optimiert wird das es vorweg > berechnet wird weil es ja dann Fest ist oder ich das ganze in Makros und > Defines umdefinieren muss. Die Macros sind Textersetzungen und haben mit der Compileroptimierung eigentlich nichts zu tun. Wenn du z.B. sowas definierst:
1 | #define x (2+3)
|
2 | |
3 | printf("%d\n", x); |
dann ersetzt der Präprozessor dieses x durch (2+3) (diese Summe wird nicht mal ausgerechnet). So steht da einfach nur:
1 | printf("%d\n", (2+3)); |
Das kannst du mit gcc -E mein_file.c sehen. Für die Optimierung ist der Compiler zuständig.
Philipp K. schrieb: > Gibt es dazu eine gute Seite die das mit den Makros einigermaßen > beschreibt? In den Artikeln die ich hier gefunden habe sind keine > Beispiele bzw. Speziell ASM Makros behandelt. Offensichtlich arbeitest du mit Arduino. Das steckt tief in der C++ Welt, und diese hat Makros zum Teil unnötig gemacht. Zumindest auch den Teil, welcher Funktionen abbilden will. Es wird also vermutlich bessere Alternativen geben, als Makro(funktionen). Leider hast du vergessen zu sagen, was du erreichen willst.
Philipp K. schrieb: > ich habe 5 Arrays die ich im Moment noch als Test vor dem (Setup) > Mainloop mit berechneten Werten auffülle, teils sind das Bitschieberei > oder auch einige For-Schleifen aus den Arduino "Defines". > > Ich habe mich jetzt gefragt ob das so optimiert wird das es vorweg > berechnet wird weil es ja dann Fest ist oder ich das ganze in Makros und > Defines umdefinieren muss. es ist nicht ganz klar, was du in defines packen willst: Die Werte, mit denen die Arrays gefüllt werden? Oder willst Du die Arrays durch #defines ersetzen? je nach Aufgabe und Randbedingung kann jede der 3 Varianten besser sein. Wenn das array größer ist als der Code zu dessen Füllung, und die Startup-Zeit nicht stört, kann Deine Version die beste sein. Mach mal ein Beispiel.
Philipp K. schrieb: > Ich habe mich jetzt gefragt ob das so optimiert wird das es vorweg > berechnet wird weil es ja dann Fest ist oder ich das ganze in Makros und > Defines umdefinieren muss. Zeig doch mal ein Minimalbeispiel. Aus den Wirren kann man nur raten.
Danke für die Antworten, da man ja bei Arduino diese freien Pinzuordnungen hat (D1,A1,etc) wollte ich mir eine Funktion bereitstellen die zum Beispiel über einen Array den man mit Pins füllt mehrere Ports mit kleinstem Overhead setzt. Normalerweise benutzt man ja digitalWrite(pin, high) da wird nur im zugehörigen port das eine bit mit Overhead gesetzt. Die Funktion benutzt dann eigentlich nur Variablen die vor dem Kompilieren bekannt sein könnten. Ich habe das schonmal in Serial fast fertig, da wird mir eine funktion zum reinkopieren als Text ausgegeben. Kann ich mal posten wenn fertig.
:
Bearbeitet durch User
Ich verstehe dich nicht... Möchtest du die Arduino Pinnummeriereung beibehalten? Aber diese nicht zur Laufzeit aufdröseln, sondern zur Compilezeit. Und dennoch die Pins in einem veränderlichen Array halten. Wie dir Makros dabei helfen sollen, kann ich leider nicht erkennen.
okay, vielleicht anders erklärt.. ich bereite im Setup mehrere Arrays vor und habe mich dann gefragt ob das so optimiert wird das letzten endes nur die Arrays im Maschinencode übrig bleiben weil alle zuständigen Werte in anderen Arrays und Variablen vorher bekannt sind. Meine Idee war dann mit Makros könnte man das dann quasi erzwingen.
Philipp K. schrieb: > Meine Idee war dann mit Makros könnte man das dann quasi erzwingen. Makros erzwingen nix. Das sind einfache Textersetzungen. Mir scheint du suchst constexpr. Das ist sozusagen die Typesichere Variante und man bekommt min. eine Warnung, wenn es nicht zur Compilezeit aufgelöst wird. Aber warum in Setup füllen?
Und warum nicht einfach bei Deklaration schon richtig befüllen statt in der init, wenn es zur Compilezeit schon bekannt ist? Dann "bleibt nur das Array". Der Lesbarkeit wegen machen hier Makros dann schon Sinn, aber mit Optimierung hat das nichts zu tun. Auf der andern Seite optimiert man da nur wenig weg, oder ist die init so zeit- bzw. ressourcenkritisch?
Das Ding ist halt ich muss aus mehreren Arrays einen bauen, mit zb. for Schleifen.. Jetzt möchte ich die QuellArrays nicht mit einkompiliert haben. Klar kann ich schnell eine exe zaubern die mir das eben vorbereitet, im Code wäre es besser.
Ganz Klar schrieb: > Der Lesbarkeit wegen machen hier Makros dann schon Sinn, Wenn nix anderes geht.... Aber solange es bessere Alternativen gibt. Wie schon gesagt, constexpr Ausdrücke, oder Funktionen, haben hier deutliche Vorteile, bei gleich guter Lesbarkeit. Ganz Klar schrieb: > aber mit Optimierung hat das nichts zu tun. Ja! Da sind Makros weder förderlich, noch hemmend. Auch schient mir hier nicht die Optimierung als ganzes gemeint zu sein, sondern nur der Teilbereich "Ausführung zur Compilezeit" Ist dem so? Philipp K. schrieb: > Das Ding ist halt ich muss aus mehreren Arrays einen bauen, mit zb. for > Schleifen.. Zeige doch endlich mal ein Beispiel.
Philipp K. schrieb: > Das Ding ist halt ich muss aus mehreren Arrays einen bauen, mit zb. for > Schleifen.. >... Wo ist das Problem? Das lässt sich doch bestimmt auch mit einem kleinen Python o. ä. schnell generieren.
Habe das mal für einen Arduino UNO durchgespielt Verwendet wird ein GCC 9.2 mit gnu++17
1 | constexpr unsigned arraySize {3}; |
2 | |
3 | using MeinArray = int[arraySize]; |
4 | |
5 | constexpr MeinArray a {1,2,3}; |
6 | constexpr MeinArray b {4,5,6}; |
7 | |
8 | struct MeinContainer |
9 | {
|
10 | MeinArray array; |
11 | };
|
12 | |
13 | constexpr MeinContainer fillContainer() |
14 | {
|
15 | MeinContainer c {{0}}; |
16 | for(unsigned i = 0; i < arraySize; i++) |
17 | {
|
18 | c.array[i] = a[i] + b[i] + i; // Beispiel für eine beliebige Berechnung |
19 | }
|
20 | return c; |
21 | }
|
22 | |
23 | void setup() |
24 | {
|
25 | constexpr MeinContainer c {fillContainer()}; |
26 | |
27 | for(unsigned i = 0; i < arraySize; i++) |
28 | {
|
29 | PORTB = c.array[i]; // Ausgabe |
30 | }
|
31 | }
|
32 | |
33 | void loop() |
34 | {
|
35 | |
36 | }
|
-- Und dieses bleibt von der Ausgabeschleife im Compilat übrig
1 | for(unsigned i = 0; i < arraySize; i++) |
2 | {
|
3 | PORTB = c.array[i]; // Ausgabe |
4 | 1a6: 85 e0 ldi r24, 0x05 ; 5 |
5 | 1a8: 85 b9 out 0x05, r24 ; 5 |
6 | 1aa: 88 e0 ldi r24, 0x08 ; 8 |
7 | 1ac: 85 b9 out 0x05, r24 ; 5 |
8 | 1ae: 8b e0 ldi r24, 0x0B ; 11 |
9 | 1b0: 85 b9 out 0x05, r24 ; 5 |
Die Arrays verschwinden vollständig.
Arduino Fanboy D. schrieb: > for(unsigned i = 0; i < arraySize; i++) > { > PORTB = c.array[i]; // Ausgabe > } Das ist fragwürdig, da PORTB immer überschrieben wird und am Ende der init der letzte Wert aus array[arraySize-1] in PORTB steht...
constexpr hört sich gut an, da muss ich nochmal nachlesen, irgendwie war ich da auch schon vorbeigekommen. Okay, mal ein kleines Beispiel auf das wesentliche beschnitten.. seven_segment_digits soll nicht miteinkompiliert werden.. Wenn ich das in Python machen will habe ich das schon in irgendwas anderem fertig gemacht bevor ich das Tutorial aufgerufen habe :D
1 | uint8_t seven_segment_digits[10][7] = { |
2 | { 1, 1, 1, 1, 1, 1, 0 }, // display '0' |
3 | { 0, 1, 1, 0, 0, 0, 0 }, // display '1' |
4 | { 1, 1, 0, 1, 1, 0, 1 }, // display '2' |
5 | { 1, 1, 1, 1, 0, 0, 1 }, // display '3' |
6 | { 0, 1, 1, 0, 0, 1, 1 }, // display '4' |
7 | { 1, 0, 1, 1, 0, 1, 1 }, // display '5' |
8 | { 1, 0, 1, 1, 1, 1, 1 }, // display '6' |
9 | { 1, 1, 1, 0, 0, 0, 0 }, // display '7' |
10 | { 1, 1, 1, 1, 1, 1, 1 }, // display '8' |
11 | { 1, 1, 1, 0, 0, 1, 1 } // display '9' |
12 | };
|
13 | |
14 | int segmentPins[] = {A0, 7 , A3, A4, A5 , A1 , A2}; // PC0-5 PD7 |
15 | |
16 | unsigned char seg_codeB[10]; |
17 | unsigned char seg_codeC[10]; |
18 | unsigned char seg_codeD[10]; |
19 | uint8_t BMask = 0; |
20 | uint8_t CMask = 0; |
21 | uint8_t DMask = 0; |
22 | |
23 | void setup() { |
24 | for (int i = 0; i < 10; i++) |
25 | for (int c = 0; c < 7; c++) { |
26 | if (seven_segment_digits[i][c] == 1) { |
27 | uint8_t bit = 0; |
28 | uint8_t pin = segmentPins[c]; |
29 | bit = digitalPinToBitMask(segmentPins[c]); |
30 | if (pin < 8) { DMask |= bit; if (seven_segment_digits[i][c] == 1) seg_codeD[i] |= bit; |
31 | }
|
32 | else if (pin < 14){ BMask |= bit; if (seven_segment_digits[i][c] == 1) seg_codeB[i] |= bit; |
33 | }
|
34 | else if (pin > 13){ CMask |= bit; if (seven_segment_digits[i][c] == 1) seg_codeC[i] |= bit; |
35 | }
|
36 | }
|
37 | }
|
38 | |
39 | }
|
40 | |
41 | |
42 | |
43 | void setnum(uint8_t num) { |
44 | uint8_t oldSREG = SREG; |
45 | cli(); |
46 | |
47 | PORTB |= (seg_codeB[num] & BMask); |
48 | PORTC |= (seg_codeC[num] & CMask); |
49 | PORTD |= (seg_codeD[num] & DMask); |
50 | SREG = oldSREG; |
51 | }
|
Ganz Klar schrieb: > Das ist fragwürdig, da PORTB immer überschrieben wird und am Ende der > init der letzte Wert aus array[arraySize-1] in PORTB steht... Es ist doch nur eine Beispiel Ausgabe. Ein weiterer Sinn ist nicht beabsichtigt. Nur um zu zeigen, dass die Arrays vollständig eliminiert werden und auch die Initialisierungsfunktion, mitsamt ihrer Schleife.
Arduino Fanboy D. schrieb: > Ein weiterer Sinn ist nicht beabsichtigt. Okay danke, leuchtet jetzt ein mit dem constexpr.
Arduino Fanboy D. schrieb: > Habe das mal für einen Arduino UNO durchgespielt Nochmal Danke, diese Antwort habe ich irgendwie überlesen :-) .. ist mir jetzt nach Zig Tagen mit Templates und constexpr wenigstens schlüssig :)
Arduino Fanboy D. schrieb: > Die Arrays verschwinden vollständig. Da stellt sich mir doch direkt die Frage nach dem Sinn Deiner Arrays, wenn sie vom Compiler einfach ignoriert werden. Vielleicht solltest Du Dein Konstrukt mal mit Leben füllen und dann nochmal den Compiler fragen.
Konstantin Qualle schrieb: > wenn sie vom Compiler einfach ignoriert werden. Werden sie nicht. Konstantin Qualle schrieb: > Vielleicht solltest Du Dein Konstrukt mal mit Leben füllen und dann > nochmal den Compiler fragen. Vielleicht solltest du mal C++ lernen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.