avr-gcc const und Pointer

Ich bin immer noch etwas verwirrt, was den avr-gcc betrifft :-(
schleierhaft :-(
Was genau bedeutet denn "const" bei Variablen-Deklarationen?
Konstanten in CONST liegen, und dieses Segment nachher im Flash Speicher
Was ist der Unterschied zwischen
const int x = 1;
und
#define x 1
Klar, ein #define hat keine Adresse, aber wenn man die nie braucht, wie
sollten dann Konstanten am besten deklariert werden, um Speicher zu
sparen? (RAM und Code)
Was ist der Unterschied zwischen "const int" und "const char"?
Lohnt es sich, kleine Werte als char oder byte zu deklarieren?
Wie werden String-Literale abgelegt?
In etlichen Beispielen wird dort ein Puffer verwendet, in den so ein
Literal kopiert wird, bevor der Puffer an weitere Funktionen als char*
Zugriffe auf Flash und RAM unterschiedlich sind, was aber gleich zur
Wie sind Pointer als Parameter implementiert?
Zeigen solche Parameter (z.B. char *
p) immer ins RAM, oder werden sie
Pointer zeigt?
Code schreibt?
DoDi
Reply to
Hans-Peter Diettrich
Loading thread data ...
Bitte was? ;-)
"const" bedeutet, dass man auf etwas nicht schreiben darf. Es bezeichnet nicht, wo es zu liegen hat. Es muss im gleichen Adressraum liegen wie eine Variable des gleichen Typs ohne "const" (bei AVR also nicht im Flash).
Wenn du den Optimizer des Compilers abgeschaltet hast kann die Variante mit #define besser sein. Ansonsten wird der Optimizer anschauen was du
ist.
ohne Angabe signed oder unsigned sein. "int" hat keine definierte Breite, mindestens 16 Bits und ist ohne Angabe signed.
Dazu wurden im anderen Thread Beispiele gepostet.
Ja.
Wenn ein Pointer ins Flash zeigen soll muss er ein entsprechendes Attribut verpasst bekommen. Siehe PROGMEM und _flash im anderen Thread bzw. hier in der Doku:
Reply to
Michael Baeuerle
Kann der avr-gcc denn jetzt schon die FLASH, EEPPROM und sram speicherbereiche unterscheiden? Soweit ich mich erinnere konnte er das nicht. Das gab dann schoen fehler wenn man eines der codebeispiele(fuer intels IAR compiler, glaub ich) aus den Atmel Appnotes compilieren wollte. Da kam dann halt was an der stelle im sram war(meist irgendein muell). Einfach den pointer zu dereferenzieren, das reichte nicht... Fuer alles eigene funktionen. Der C standard erlaubt soweit ich mich erinnern tu', das aendern von const variablen (ist wie in dem Piratenfilm eher eine Richtlinie).
Reply to
Johann Klammer
Beispiel: ------------------------------------------------------------------------ $ cat constant.c #include
void bla(void) { const char x = 1;
PORTB = x; } ------------------------------------------------------------------------
ergibt: ------------------------------------------------------------------------ $ avr-gcc -Os -mmcu=atmega128 -c -o constant constant.c $ avr-objdump -d constant
constant: file format elf32-avr
Disassembly of section .text:
00000000 : 0: 81 e0 ldi r24, 0x01 ; 1 2: 88 bb out 0x18, r24 ; 24 4: 08 95 ret ------------------------------------------------------------------------
Da ist also nichts im RAM gelandet.
Reply to
Michael Baeuerle
Keine Ahnung was du da meinst. Aber der gcc akzeptiert garantiert kein C++. Der g++ vielleicht.
Das ist der Hinweis an den Compiler, dass der Inhalt sich nicht
Wat? "traditionell"? Und was ist am avr-gcc da untraditionell? Das ist ein ganz normaler gcc. Ein CONST Segment ist mir auch unbekannt, ich nehme an du meinst .rodata oder .text?
Wenn du ein globales Array einfach nur const deklarierst, dann legst du
ist der einzige memory-mapped Speicherbereich eben das SRAM und da landet er dann. Das hat aber nichts mit dem avr-gcc zu tun, sondern mit dem C-Standard.
Musst du ins Assembly schauen. Kommt immer drauf an. Global oder
deklariert ist (daher ist ersteres zu bevorzugen). #defines sollte man eh nur einsetzen, wo es kein entsprechendes Sprachkonstrukt gibt.
von globalen Variablen oder von funktionslokalen?
Datentypen, siehe C-Standard. Ein char ist 8 Bit lang, ein int mindestens 16 Bit lang (auf dem AVR exakt 16 Bit).
Wenn du nichts weiter spezifizierst im RAM (wegen MMIO, s.o.).
Das sind 16 Bit Werte.
verwendest. Also wenn du einen char PROGMEM * (einen Pointer auf einen
(ohne Warnung!) uminterpretiert.
Ne.
Das hat alles mit dem avr-gcc nichts zu tun, sondern eher mit C
willst.
Johannes
--
>> Wo hattest Du das Beben nochmal GENAU vorhergesagt? 


Kosmologen: Die Geheim-Vorhersage.
Reply to
Johannes Bauer
Oder liegt diese Vorverarbeitung in der Arduino IDE (*.ino --> *.cpp)?
[...]
DoDi
Reply to
Hans-Peter Diettrich
Du redest jetzt nicht von avr-gcc, sondern von arduino, richtig?
anders" ist. Ein nackter avr-gcc will nur C, und avr-c++ nur C++.
24-Bit-Pointer, aber wenn Du arduino benutzt, wirst Du so einen kaum haben.
cu Michael
Reply to
Michael Schwingen
Michael Schwingen schrieb:
Ah ja, das ist ja schon mal ein Meilenstein auf meinem Einstieg :-)
DoDi
Reply to
Hans-Peter Diettrich
Am 23.03.2015 um 16:32 schrieb Michael Baeuerle:
Die GNU Coding Rules bevorzugen ja die Const-Variante da der Compiler
Allerdings funktioniert das:
const uint8_t bufSize=20; char buffer[bufSize];
not const". Hier muss man define nehmen.
Nebenbei meine ich auch das
typedef int counter_t; counter_t cnt; int x; ... cnt=x;
Robert
Reply to
Robert Loos
Robert Loos schrieb:
Deshalb ja meine Frage, ob man bei kleinen Konstanten besser byte nehmen sollte.
Bei Arduino funktioniert das mit const int bufSize = 100;
DoDi
Reply to
Hans-Peter Diettrich
werden) sollte das auch so funktionieren.
Ist doch auch (real) der gleiche Typ.
Reply to
Michael Baeuerle
Kann ich dir leider nicht sagen, ich programmiere AVRs immer direkt
Reply to
Michael Baeuerle
Am 24.03.2015 um 11:43 schrieb Michael Baeuerle: ...
Ja jetzt! Aber diese Zuweisung ist wahrscheinlich schon bei der
Reply to
Robert Loos
Robert Loos schrieb:
Von C darfst Du keine Typsicherheit erwarten, die auf Typnamen basiert. IMO vereinfachen typedefs nur dem Compiler das Parsen von Deklarationen,
bezeichnet.
auszugeben. Stell Dir nur mal vor, wieviele verschiedene
DoDi
Reply to
Hans-Peter Diettrich
Hallo Hans-Peter,
Hans-Peter Diettrich schrieb:
Fehlermeldungen auszuspucken, wenn man ein wirklich striktes Typsystem hat, noch ist das ein Problem, bei Aufruf eine Standardfunktion entweder selbst eine Typwandlung zu machen oder eben eine weitere Version dieser Standardfunktion zu erstellen, die nichts weiter macht, als die Typwandlung
Aufruf der Funktion hat.
Fehler vermeidet. Ein Sprache, die implizite Typwandlungen macht, ist kaputt.
Reply to
Martin Schoenbeck
Martin Schoenbeck schrieb:
Ein funktionierendes Typsystem erlaubt dem Compiler, erlaubte von unerlaubten Konvertierungen zu unterscheiden. Ein "unsigned" Wert kann
werden, da ist keine Fehlermeldung und nicht mal eine Warnung notwendig. Bei "signed" Werten wird es problematischer, die lassen sich an "unsigned" nicht zuweisen, wenn sie negativ sind. Aber auch da ist
Geschmack zu viele) implizite Umwandlungen gestattet :-]
DoDi
Reply to
Hans-Peter Diettrich
Am 24.03.2015 um 18:57 schrieb Hans-Peter Diettrich: ...
nicht mehr als bisher. Ich will Typumwandlungen ja nicht verbieten. Ich
itoa(cnt) eine Warnung absetzt und bei itoa((int)cnt) nicht, da die Typen kompatibel sind.
Robert
Reply to
Robert Loos
Hallo Hans-Peter,
Hans-Peter Diettrich schrieb:
einbauen. Das ist nicht das, was ich unter einem funktionierenden Typsystem verstehe, denn da definiere _ich_ als Entwickler, welche Eigenschaften ein
treffen.
grauenhaft.
ausgereiftes Typsystem hat, sondern wenn sie implizit konvertiert. Das
denke, niemand wird ernsthaft bestreiten wollen, jedenfalls vom Standpunkt
bequemer als Assembler.
Reply to
Martin Schoenbeck
definiertes Verhalten: | | A computation involving unsigned operands can never overflow, because | a result that cannot be represented by the resulting unsigned integer | type is reduced modulo the number that is one greater than the largest | value that can be represented by the resulting type.
Beispiel: --------------------------------------- unsigned int a = UINT_MAX; unsigned int b = 0;
a = a + 1U; if (a == b) { ... ---------------------------------------
Reply to
Michael Baeuerle
Martin Schoenbeck schrieb:
Nein, das geht z.B. in Delphi (OPL) mit einem einzigen Datentyp: type TMyNumber = low..high; int8_t = -128..127; uint8_t = 0..$FF;
vordefinierten Datentyp festlegen, der dann irgendwann oder auf
dessen bekannte Grenzen einsetzen.
der Standardtyp (int, integer...) bei allen derzeitigen general-purpose Compilern bei 32 Bit. Bei Mikrocontrollern auch mal weniger, da wird das
beliebiger Genauigkeit.
DoDi
Reply to
Hans-Peter Diettrich

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.