mikrocontroller.net

Forum: Compiler & IDEs Verständnisproblem bei Makro


Autor: Tobias M. (eule)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
bin gerade dabei ein bestehendes µC-Programm eines ATMEL-Controllers, in 
C-Code, umzuschreiben um es auf einem anderen µC laufen zu lassen. Dabei 
bin ich auf folgendes Makro gestoßen, welches mir Verständnisprobleme 
bereitet:

   #define FlashConst(s) (__extension__({static unsigned char __c[] 
PROGMEM =
   (s); &__c[0];}))

Ist jemand in der Lage mir diesen Qellcode zu erläutern?

Danke im voraus...

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, als erstes solltest du eine beispielhafte Makroersetzung
durchführen.  Nehmen wir mal an, du hast irgendwo:
  cp = FlashConst("Hello, world!");

dann ergibt sich daraus:
  cp = (__extension__({static unsigned char __c[] __attribute__((__progmem__)) = ("Hello, world!"); &__c[0];}))

Dabei hast du folgende Teile:
__extension__
markiert den nachfolgenden Konstrukt als eine Erweiterung (des GCC)
zum C-Standard.  Damit wird es bei -std=c89 oder -std=c99 nicht
angewarnt, weil dem Compiler explizit mitgeteilt wird, dass sich
der Entwickler darüber im Klaren ist, dass der Konstrukt nicht dem
Standard entspricht.
static unsigned char __c[]
eine normale statische Variable, die lokal zum soeben angelegten
Block ist.
__attribute__((__progmem__))
eine Sonderanweisung an den GCC, die damit deklarierte Variable statt
im SRAM des AVR im Flash-ROM unterzubringen.

Danach folgt eine gewöhnliche Initialisierung dieser Variable mit
der übergebenen Zeichenkettenkonstanten.
&__c[0];
Es wird die Adresse des ersten Elements der statischen Variablen
gebildet und als Ausdruck verwendet.  Da dieser Ausdruck der letzte
innerhalb des umschließenden Blocks ist, gibt der Block dessen Wert
(ähnliche der “return”-Anweisung einer Funktion) zurück, d. h. er
darf auf der rechten Seite einer Zuweisung benutzt werden.

Die Möglichkeit, dass ein Block einen Wert zurückgeben kann, ist die
eigentliche Spracherweiterung des GCC, für die einleitend das
__extension__-Schlüsselwort notwendig geworden ist.

Ob andere Compiler über ähnliche Mechanismen verfügen wie GCC hier,
lässt sich nicht ohne weiteres sagen.  Ohne C-Spracherweiterungen ist
die entsprechende Funktionalität nicht implementierbar (zumindest nicht
auf diese Weise), daher wurde dieser vergleichsweise umständliche
Konstrukt gewählt.

Autor: Tobias M. (eule)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich könnte also demnach auch eine Funktion definieren, mit einem 
"unsigned char"-Array und einem Zeiger in dem die Adresse des ersten 
Elementes dieses Arrays gespeichert wird als Parameter?

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die Frage verstehe ich so nicht...

Erstens, nicht "unsigned char", sondern "char".  Es handelt sich um
Zeichenkettenkonstanten, und die sind per definitionem immer vom
Typ char[], nicht signed char[], auch nicht unsigned char[].

Zweitens schrieb ich doch: mir ist keine Möglichkeit bekannt, die
gleiche Funktionalität auf irgendeine Weise mit Mitteln zu erreichen,
die komplett vom C-Standard abgedeckt sind.

Autor: Tobias M. (eule)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tut mir leid, ich bin absoluter Anfänger im Thema µC und im 
Programmieren mit C. Mir würde es ausreichen wenn ich eine Funktion 
hätte die als Argument eine    Zeichenkette erwartet und die Adresse des 
ersten Elements dieser Kette als Rückgabewert dient.- Ich hoffe das ist 
jetzt einigermaßen verständlich.

Aber im Original-Quelltext steht
unsigned char
.

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Mir würde es ausreichen wenn ich eine Funktion hätte die als Argument
> eine Zeichenkette erwartet und die Adresse des ersten Elements dieser
> Kette als Rückgabewert dient.

Dazu brauchst du keine Funktion. Wenn du das Array verwendest, wird 
automatisch die Adresse des ersten Elements dafür eingesetzt.

> Aber im Original-Quelltext steht
> unsigned char

Funktionieren wird's vermutlich trotzdem, aber richtig ist eben 
eigentlich nicht.

Autor: Jörg Wunsch (dl8dtl) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Rolf Magnus wrote:

> Dazu brauchst du keine Funktion. Wenn du das Array verwendest, wird
> automatisch die Adresse des ersten Elements dafür eingesetzt.

Allerdings hat der Makro im Original halt was anderes getan: er hat
den String im Flash-ROM platziert und dann dessen Adresse ermittelt.
Wenn dein Zielprozessor sowas nicht braucht, dann kannst du den
Makro wahrscheinlich durch einen Nullmakro ersetzen:
#if defined __AVR__
#  define FlashConst(s) // hier das, was du schon kennst
#elif defined __FOOBAR__ // Test für Zielprozessor FOOBAR
#  define FlashConst(s) (s)
#else
#  error "Unknown target CPU"
#endif

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.