C Pointer schieben?

Gast #5539375
Kurze Frage zum Thema Pointer Arithmetik..
1
void    dmaSetSource          ( uint8_t channel , void* source )       {   CHANNEL(channel).SRCADDR0 = ( uintptr_t )  source & 0xff;   CHANNEL(channel).SRCADDR1 = ( ( uintptr_t )  source >> 8 ) & 0xff;   CHANNEL(channel).SRCADDR2 = ( ( uintptr_t ) source >> 16 ) & 0xff; }

Bei dem schieben von den Werten, bekomme ich ein Haufen Warnungen..
Wieso?
Moderator
Es wird kein Pointer geschoben, da source vorher nach uintptr_t
gecastet wird. Die Warnungen (wie auch immer die lauten) beziehen sich
also auf etwas anderes.

Edit: Einen Pointer zu schieben ist nicht erlaubt und ergäbe deswegen
keine Warning, sondern einen Error.
Dergute W. schrieb:
>> Bei dem schieben von den Werten, bekomme ich ein Haufen Warnungen..
>> Wieso?
>
> Weil das dem compiler verdaechtig vorkommt.

Nicht nur dem Compiler ... ;-)

Bei C sind IIRC nur + und [] als Operatoren auf Pointer erlaubt.

Exotische Plattformen benutzen mitunter abweichende Pointer Formate, man 
denke beispielsweise an 16-bittiges DOS (8086), welches 32-Bit in 16 Bit 
Segment und 16 Bit Offset unterteilt. Damit wären Shifts nicht ohne 
weiteres möglich.

Bei bekanntem Pointer Verhalten des Compilers kann man auf den 
entsprechenden unsigned Typ casten, z.B. uint32_t für 32-Bit ARM.
Marcus schrieb:
> Wenn ich den Teil auskommentiere sind die Fehlermeldungen bzw. Warnungen
> weg.
> Es hat eindeutig damit was zu tun!

Dann zeige uns doch mal den kompletten Source (Anhang als .c Datei) und 
die kompletten Fehlermeldungen / Warnings. Ansonsten wird das ein 
heiteres Ratespiel.
Moderator
Marcus schrieb:
> Wenn ich den Teil auskommentiere sind die Fehlermeldungen bzw. Warnungen
> weg.
> Es hat eindeutig damit was zu tun!

Es hat etwas mit diesen Codzeilen zu tun, aber nicht mit dem Schieben
eines Pointers.

Vielleicht magst du uns ja den Wortlaut der Warnungen verraten :)
Gast
warum castest Du nicht einfach zu Beginn zu einem Integer?

also z.B. size_t x=(size_t) source;

Und dann halt die Berechnungen, nachher cast zum Pointer und dann die 
Angabe der Fehlermeldungen hier.
Gast
Hier die Fehlermeldung
1
Severity  Code  Description  Project  File  Line
2
Warning    right shift count >= width of type [-Wshift-count-overflow]  DMA  c:\users\marcus\Documents\Atmel Studio\7.0\DMA\DMA\xmega_dma.c  69
Gast
Cyblord -. schrieb:
> Marcus schrieb:
>> Hier die Fehlermeldung
>>> Severity  Code  Description  Project  File  Line
>> Warning    right shift count >= width of type [-Wshift-count-overflow]
>> DMA  c:\users\marcus\Documents\Atmel Studio\7.0\DMA\DMA\xmega_dma.c  69
>>
> Ist doch eindeutig und verständlich wo das Problem liegt.
Weil es nur ein 16 Bit Typ ist?
Gast
Marcus schrieb:

>>> Warning    right shift count >= width of type [-Wshift-count-overflow]
>>> DMA  c:\users\marcus\Documents\Atmel Studio\7.0\DMA\DMA\xmega_dma.c  69

> Weil es nur ein 16 Bit Typ ist?

Nö, weil "right shift count >= width of type". Es spielt für diese 
Warnung keine Rolle, welcher Typ es genau ist, das einzige, was eine 
Rolle spielt: es wird so weit geschoben, dass immer nur 0 oder -1 
rauskommen kann.

Sprich: du kannst dir das Schieben sparen und im Falle eines unsigned 
Types einfach 0 zurückgeben, im Falle eines signed Types je nach 
Vorzeichen 0 oder -1.

Oder anders ausgedrückt: dein Code ist offensichtlicher logischer 
Schwachsinn, so offensichtlich, dass es sogar der Compiler bemerken 
kann, der logische Fehler normalerweise eher nicht aufspüren kann. Das 
ist allerdings auch nicht seine Aufgabe, der hat eigentlich nur die 
syntaktische Korrektheit zu prüfen, aber wenn's gerade abfällt, ist es 
doch nett von ihm, den unfähigen User auf seinen Fehler mit einer 
Warnung hinzuweisen, oder?
Lass mal das casten auf uintptr_t weg.
Also
1
void dmaSetSource (uint8_t channel , void *source)
2
{   
3
  CHANNEL(channel).SRCADDR0 =  source        & 0xff;
4
  CHANNEL(channel).SRCADDR1 = (source >>  8) & 0xff;
5
  CHANNEL(channel).SRCADDR2 = (source >> 16) & 0xff; 
6
}
Moderator
Ich kenne mich mit den XMegas nicht gut aus. Trotzdem ein Versuch:

Falls du maximal 64k RAM in deinem System hast, kannst du SRCADDR2
einfach auf 0 setzen, und der Käse sollte gegessen sein:

1
CHANNEL(channel).SRCADDR2 = 0;

Falls du (inkl. externen Speicher) mehr als 64k RAM hast und du mit dem
DMA-Controller auch den Adressbereich >64k ansprechen willst, geht das
IMHO nicht mit normalen C-Pointern. Du müsstest dann source statt als
Poiunter als __uint24 oder uint32_t deklarieren und den Code, der
dmaSetSource aufruft, und ggf. noch weitere Programmteile entsprechend
anpassen.
Gast
Eine Frage hätte ich da noch..
1
void    dmsSetSourceChannel          ( uint8_t channel , uint32_t *source );
1
void    dmsSetSourceChannel                ( uint8_t channel , uint32_t *source )      
2
{
3
  CHANNEL(channel).SRCADDR0 = *source & 0xFF;
4
  CHANNEL(channel).SRCADDR1 = ( *source >> 8 ) & 0xFF;
5
  CHANNEL(channel).SRCADDR2 = ( *source >> 16) & 0xFF;
6
}

Ist es korrekt, dass "source" die Adresse übergibt oder aktuell ( so wie 
im Kode zu sehen ) den Inhalt?

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 8 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.