mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Frage: Pointer-Deklaration


Autor: Bernd Bubble (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

kurze Frage aus der Pfalz:

im Header-file zum LPC2294 wird die Adresse des CANMOD-Registers wie 
folgt definiert:

#define C1MOD (*((volatile unsigned long*)))  0xE0044000



Später im einer anderen Routine wird einem Pointer diese Adresse wie 
folgt zugewiesen:


unsigned long *pBase

pBase = (unsigned long*) &C1MOD;


Warum wird hier noch einmal der Typ angegeben? Das ist doch 
normalerweise ein Typecast, ist dieser hier wirklich nötig?
Und wofür das Doppel* in der Definition des Registers?

Kann mir jemand bei diesen Fragen helfen?

Danke,
Bernd

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd Bubble schrieb:

> Warum wird hier noch einmal der Typ angegeben? Das ist doch
> normalerweise ein Typecast, ist dieser hier wirklich nötig?

Ohne den Cast würde es eine "discards qualifiers"-Warnung geben.

> Und wofür das Doppel* in der Definition des Registers?

Das erste '*' ist Bestandteil des Cast, um aus dem Hex-Wert einen 
Pointer zu machen, das zweite '*' ist zur Dereferenzierung dieses 
Pointers.

Edit: Oder umgekehrt, je nach dem, von welcher Seite man anfängt zu 
zählen. ;-)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dass sieht seltsam aus.

Bist du sicher, dass du das richtig hier ins Forum kopiert hast.

IMHO sollte das eigentlich lauten
#define C1MOD (*((volatile unsigned long*)0xE0044000))  

so ergibt das Sinn, aber deine Variante ist ... zumindest seltsam

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Poste doch mal den richtigen Code. So, wie das da steht, kann das nicht 
sein.

Oliver

Autor: Bernd Bubble (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl Heinz,

du hattest recht:

#define C1MOD          (*((volatile unsigned long *) 0xE0044000))

aber kannst du mir in wenigen verständlichen Worten die Deklaration 
erklären.

Mir ist klar, dass man dem Register einen Adresswert zuweisen will, und 
dass im Programm die Adresse an Pointer vom Typ unsigned long übergeben 
werden soll...ich hätte gesagt, dass der erste * zur Dereferenzierung 
verwendet wird???

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bernd Bubble schrieb:
> Karl Heinz,
>
> du hattest recht:
>
> #define C1MOD          (*((volatile unsigned long *) 0xE0044000))
>
> aber kannst du mir in wenigen verständlichen Worten die Deklaration
> erklären.
>
> Mir ist klar, dass man dem Register einen Adresswert zuweisen will, und
> dass im Programm die Adresse an Pointer vom Typ unsigned long übergeben
> werden soll...ich hätte gesagt, dass der erste * zur Dereferenzierung
> verwendet wird???

Yep.

Aber gehe es doch einfach von innen nach aussen, beginnend beim Wert 
durch

  0xE0044000
               ist eine bestimmte Zahl

  (volatile unsigned long *) 0xE0044000
               diese Zahl wird zu einem Pointer gecastet

  *Pointer
               gibt den Inhalt an der Adresse die im Pointer steht

  Also

  * (volatile unsigned long *) 0xE0044000

      ergibt den Inhalt, der sich an dem unsigned long Pointer,
      dessen Wert 0xE0044000 beträgt. (Das volatile besagt lediglich,
      dass jedesmal nachgesehen werden muss, wenn mit dem Inhalt etwas
      passiert. Cachen ist nicht erlaubt)

Und dann noch eine Klammer rundherum, wie es bei Makros generell ratsam 
ist.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Erstmal ist das keine Zuweisung, sondern nur ein #define.
Es wird also in Zukunft C1MOD erstzt durch das, was hier dahinter steht.

Das ist dann wiederum so zu interpretieren:
a) 0xE0044000 ist eine ganze Zahl
b) (volatile unsigned long *) 0xE0044000 ist eben diese Zahl, aber
  interpretiert als Zeiger auf unsigned long.
  Gemeint ist damit die Adresse einer unsigned long an der Stelle
  0xE0044000 im Speicher.
c) *((volatile unsigned long *) 0xE0044000) ist dann das, was an
  besagter Stelle im Speicher steht, also die unsigned long an
  der Stelle 0xE0044000
d) die Klammern drumrum sollen Ärger verhindern, der durch
  die unglückliche Auswertungsreihenfolge der Operatoren
  bei der jeweiligen Verwendung vorkommen kann.
  Man gewöhnt sich einfach an, solche Ersetzungen zu klammern.

Tip: In jedem besseren C-Buch die Operatoren anschauen und
dabei die Prioritäten und Auswertungsreihenfolge beachten
(Zusammenfassung von links oder von rechts).

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ja; bin ja auch nicht Karl-Heinz und war damit nicht gemeint.

Autor: Bernd Bubble (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok..ist jetzt klar...danke an Karl-Heinz und ausdrücklichen Dank auch an 
Klaus...

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.