Warum verwenden Benutzer eine Variable, um eine PIN-Nummer anzugeben, wenn sich die PIN während der Ausführung des Codes wahrscheinlich nicht ändert?
Oft sehe ich ein int
Wesen, das für eine Stiftdefinition verwendet wird,
int led = 13;
wenn die Verwendung von a const int
const int led = 13;
#define LED 13
macht viel mehr Sinn.
Es ist sogar in Tutorials auf der Arduino-Site, zum Beispiel das erste Tutorial, das die meisten Leute ausführen, Blink .
Ich lese irgendwo , const int
was vorgezogen wird #define
. Warum wird dies nicht von Anfang an ermutigt, anstatt den Menschen von Anfang an zu erlauben, schlechte Gewohnheiten zu entwickeln? Ich habe es vor einiger Zeit bemerkt, aber in letzter Zeit hat es mich gereizt, daher die Frage.
Speicher / Verarbeitung / Rechen weise ein const int
, enum
oder was das betrifft #define
, besser als eine einfache int
, nimmt also weniger Speicher, gespeichert in verschiedenen Speicher (Flash, EEPROM, SRAM), eine schnellere Ausführung, schneller zu kompilieren?
Dies scheint ein Duplikat von zu sein. Ist es besser, #define oder const int für Konstanten zu verwenden? Aber ich gehe auf die Frage ein, warum Menschen Variablen verwenden und wie sich die Leistung verbessert, wenn sie dies nicht tun, anstatt welche Art von Konstante besser ist.
quelle
Antworten:
Das ist die richtige Methode. Oder auch:
Wie viele Pins hast du?
Einige der Tutorials haben nicht so viele Qualitätskontrollen durchlaufen, wie sie haben könnten.
Die Leistung wird bei der Verwendung besser
const byte
, verglichen mitint
dem Compiler, der möglicherweise klug genug ist, um zu erkennen, was Sie tun.Was Sie tun können, ist, Menschen sanft zu ermutigen, effizientere Techniken zu verwenden, indem Sie sie in Ihrem eigenen Code verwenden.
Antworten auf Kommentare
Ein Kommentator hat vorgeschlagen, dass dies
byte
nicht Standard C ist. Dies ist korrekt, es handelt sich jedoch um eine Arduino StackExchange-Site, und ich glaube, dass die Verwendung von Standardtypen, die von der Arduino IDE bereitgestellt werden, akzeptabel ist.In Arduino.h gibt es diese Zeile:
Beachten Sie, dass dies nicht genau dasselbe ist wie
unsigned char
. Siehe uint8_t vs unsigned char und Wann ist uint8_t ≠ unsigned char? .Ein anderer Kommentator hat vorgeschlagen, dass die Verwendung von Byte nicht unbedingt die Leistung verbessert, da Zahlen, die kleiner sind als
int
die, auf dieint
heraufgestuft wird (siehe Regeln für die Heraufstufung von Ganzzahlen, wenn Sie mehr dazu möchten).Im Kontext eines konstanten Bezeichners generiert der Compiler jedoch in jedem Fall effizienten Code. Das Zerlegen von "blink" ergibt beispielsweise Folgendes in der ursprünglichen Form:
Tatsächlich wird derselbe Code generiert, unabhängig davon, ob
13
:#define
const int
const byte
Der Compiler weiß, wann eine Zahl in ein Register passt und wann nicht. Es wird jedoch empfohlen , eine Codierung zu verwenden, die auf Ihre Absicht hinweist . Machen Sie
const
es deutlich, dass sich die Zahl nicht ändert, und machen Sie esbyte
(oderuint8_t
) klar machen, dass Sie eine kleine Zahl erwarten.Verwirrende Fehlermeldungen
Ein weiterer wichtiger Grund, den Sie vermeiden sollten,
#define
sind die Fehlermeldungen, die Sie erhalten, wenn Sie einen Fehler machen. Betrachten Sie diese "Blink" -Skizze, die einen Fehler aufweist:Auf der Oberfläche sieht es OK aus, aber es erzeugt diese Fehlermeldungen:
Sie schauen auf die erste hervorgehobene Zeile (Zeile 4) und sehen nicht einmal ein "=" - Symbol. Außerdem sieht die Leitung gut aus. Jetzt ist es ziemlich offensichtlich, wo das Problem liegt (
= 13
wird ersetzt)LED
), aber wenn die Zeile 400 Zeilen weiter unten im Code steht, liegt das Problem nicht an der Art und Weise, wie die LED definiert ist.Ich habe schon viele Male gesehen, wie Menschen darauf hereinfielen (einschließlich meiner selbst).
quelle
int
Overkill ist ... das heißt, bis Arduino endlich mit dem Tera- Board herauskommt ... :-)byte
Typ . Du meinstunsigned char
.byte
stattint
, da in den meisten Kontexten Integer - Wert mit Typ kleiner alsint
gefördert zuint
.C doesn't have a byte type. You mean unsigned char.
- Meine Antwort war im Arduino-Kontext, der dies hattypedef uint8_t byte;
. Für einen Arduino ist die Verwendungbyte
also in Ordnung.Performance won't necessarily be better with byte instead of int
- siehe geänderten Beitrag.Wie Ignacio zu Recht feststellt, liegt es im Grunde daran, dass sie es nicht besser wissen. Und sie wissen es nicht besser, weil die Leute, die sie unterrichteten (oder die Ressourcen, die sie beim Lernen verwendeten), es nicht besser wussten.
Ein Großteil des Arduino-Codes und der Tutorials wurde von Personen geschrieben, die noch nie eine Programmierschulung absolviert haben, und werden von Personen, die selbst eine Autodidaktin sind und keine ausreichende Programmierschulung besitzen, aus Ressourcen "autodidaktisch" unterrichtet.
Viele der Code-Schnipsel von Tutorials, die ich überall sehe (und insbesondere die, die nur in YouTube-Videos verfügbar sind - urgh), wären eine nicht bestandene Marke, wenn ich sie in einer Prüfung markieren würde.
Ja, a
const
wird einem nicht konstanten vorgezogen, und sogar einem#define
, weil:const
(wie ein#define
, im Gegensatz zu einem Nicht-Konstanten) reserviert keinen RAMconst
(wie eine Nicht-Konstante, aber anders als a#define
) gibt dem Wert einen expliziten TypDer zweite Punkt ist dort von besonderem Interesse. Sofern bei eingebettetem Typ-Casting (
(long)3
) oder einem Typ-Suffix (3L
) oder dem Vorhandensein eines Dezimalpunkts (3.0
) nicht ausdrücklich anders angegeben , ist#define
eine Zahl immer eine Ganzzahl, und alle mit diesem Wert durchgeführten mathematischen Berechnungen sind wie eine ganze Zahl. Meistens ist das kein Problem, aber Sie können in interessante Szenarien geraten, wenn Sie versuchen,#define
einen Wert zu speichern, der größer als eine Ganzzahl ist,#define COUNT 70000
und dann eine mathematische Operation mit anderenint
Werten ausführen . Mit a könnenconst
Sie dem Compiler mitteilen, dass "dieser Wert als dieser Variablentyp behandelt werden soll". Sie würden also stattdessen Folgendes verwenden:const long count = 70000;
und alles würde wie erwartet funktionieren.Es hat auch den Anstoßeffekt, dass es den Typ überprüft, wenn der Wert um die Stelle herum übergeben wird. Versuchen Sie, eine
const long
an eine Funktion zu übergeben, die eine erwartet,int
und die sich über die Einschränkung des Variablenbereichs beschwert (oder die je nach Szenario gar nicht kompiliert werden kann). Tun Sie das mit a#define
und es würde Ihnen nur still weiter die falschen Ergebnisse liefern und Sie stundenlang am Kopf kratzen lassen.quelle
const
Variable je nach Kontext möglicherweise RAM benötigt, z. B. wenn sie mit dem Rückgabewert einer Nicht-Constexpr-Funktion initialisiert wird.const int foo = 13; bar(&foo);
der Compiler auf jeden Fall den tatsächlichen Speicher zuweisenfoo
.int
Compiler passt, wird der Wert als der kleinste Typ behandelt, in den er passt (Modulo-Regeln für vorzeichenbehaftete und nicht vorzeichenbehaftete). Wenn Sie auf einem System sind , woint
16 Bit ist,#define count 70000
wird in Folgecount
, die wie einlong
, als ob es so definiert worden warconst long count = 70000;
. Wenn Sie eine dieser Versionencount
an eine erwartete Funktion übergebenint
, behandelt sie jeder vernünftige Compiler gleich.#define COUNT 70000
wird nicht in ein Int abgeschnitten, aber der Compiler behandelt es als einen Typ, der groß genug ist, um diese Zahl aufzunehmen. Es ist wahr, dass es vielleicht nicht offensichtlich ist, wenn Sie verwenden,COUNT
dass es kein Int ist, aber Sie könnten das Gleiche über ein Int sagenconst long
.COUNT
in Ihrem Beispiel wird vor der Kompilierung durch den Ausdruck ersetzt70000
, dessen Typ durch die Regeln der Literale definiert ist, genau wie2
oder13L
oder4.0
werden durch die Regeln der Literale definiert. Die Tatsache, dass Sie#define
diese Ausdrücke als Alias verwenden, ist irrelevant. Sie können#define
beliebige Teile von C-Code als Alias verwenden, wenn Sie möchten.Als zweiwöchiger Neuling bei Arduino würde ich die allgemeine Idee aufgreifen, dass Arduino von Nicht-Programmierern besetzt ist. Die meisten von mir untersuchten Skizzen, einschließlich derjenigen auf der Arduino-Website, weisen einen völligen Mangel an Ordnung auf. Skizzen, die nicht funktionieren, und kaum ein zusammenhängender Kommentar sind in Sicht. Flussdiagramme sind nicht vorhanden, und die "Bibliotheken" sind ein nicht moderiertes Durcheinander.
quelle
Meine Antwort ist ... sie machen es, weil es funktioniert. Es fällt mir schwer, in meiner Antwort keine Frage zu stellen wie "Warum muss es 'falsch' sein?"
quelle