mikrocontroller.net

Forum: Compiler & IDEs memcpy-Warnung


Autor: Owen Senmeis (senmeis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

bei der Kompilierung bekommt man eine Warnung:
"passing arg1 of 'memcpy' discards qualifiers from pointer target type"

fuer diese Zeile:
memcpy(pwm_setting, pwm_setting_tmp, 8);

wobei
volatile uint8_t pwm_setting[8] = {33, 33, 33, 33, 33, 33, 33, 33};  
volatile uint8_t pwm_setting_tmp[8] = {27, 40, 3, 17, 150, 99, 5, 9}; 

Ist es schlimm?

Gruss
Senmeis

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ist nicht schlimm, nur sind die memcpy-Parameter ohne "volatile" 
deklariert, daher das Gemecker. Kannst du vermeiden mit:
  memcpy((void *)pwm_setting, (void *)pwm_setting_tmp, 8);

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

Bewertung
0 lesenswert
nicht lesenswert
A. K. wrote:

> Kannst du vermeiden mit:

Das ist aber sowas die Beseitigung eines Flecks mit der Fleckenschere.
;-)

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fällt dir was besseres ein?

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

Bewertung
0 lesenswert
nicht lesenswert
Wenn es mit Wegwerfen des volatile funktioniert (per Typecast), dann
war das volatile wohl auch von vornherein überflüssig, und man kann
es auch gleich ganz weglassen.

Man kann ja auch den umgekehrten Weg gehen: das volatile nur dann
per Typecast anwenden, wenn es wirklich gebraucht wird.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Manche betrachten "volatile" bei Arrays als überflüssig. Sicher bin ich 
mir da nicht, allerdings sorgt mindestens die stete Gefahr von Aliasing 
üblicherweise dafür dass da nichts anbrennt.

Es funktioniert in diesem Zusammenhang mit oder ohne Wegwerfen von 
"volatile", nur gibt's ohne dies eine letztlich ablenkende Warnung.

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Genau genommen sind explizite und ganz besonders implizite Umwandlungen 
von und nach "void *" nicht viel besser als Casts die "volatile" 
entfernen. Denn sie können die Erkennung von Aliasing aushebeln, weshalb 
Compiler und Programmierer entsprechend wachsam sein müssen. Und weil 
"char *" früher die Rolle von "void *" einnahm müssen Compiler auch 
damit (per Definition) anders umgehen als mit anderen Typen. Walter 
Bright (Autor vom Zortech/Symantec/DigitalMars Compiler) hatte anno 
Zortech C/C++ eine eigene Ansicht zum Umgang mit "void *", und ich bin 
geneigt ihm dabei Recht zu geben.

So frage ich mich auch, ob es nicht bessere Konzepte für das hinter 
"volatile" stehende Problem geben kann, als ebendieses Attribut mit 
seinen hässlichen Nebeneffekten (wie beispielsweise ineffiziente oder 
umständlich zu programmierende Interrupt-Routinen). Aber das Kind ist 
nun einmal im Brunnen und eine sauber durchdachte Sprache wird C auch in 
diesem Jahrhundert nicht mehr werden.

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

Bewertung
0 lesenswert
nicht lesenswert
A. K. wrote:
> Manche betrachten "volatile" bei Arrays als überflüssig.

Meistens ist es das.  Mein Argument ist eher andersrum: wenn denn
alles ordentlich funktioniert ohne volatile (und das explizite oder
implizite Wegwerfen der volatile-Kennzeichnung per Übergabe an
memcpy oder auch per Typecast bedeutet letztlich, dass es auch jetzt
bereits ohne volatile läuft), dann war die Angabe des volatile bei
der Deklaration ganz offensichtlich (zumindest für diesen Compiler)
gar nicht notwendig.  Wenn sie notwendig gewesen wäre, dann hätte
sich mit dem Aufruf von memcpy() (egal ob mit oder ohne Warnung oder
mit oder ohne Unterdrückung der Warnung per Typecast) ein Fehlverhalten
eingestellt.

Es kann ja sein, dass das volatile dann noch an anderen als den hier
gezeigten Stellen notwendig ist, aber dann kann man an diesen Stellen
auch explizit den Typecast nach volatile angeben stattdessen.  Bspw.
könnte man das berühmt berüchtigte Flag, das in der ISR gesetzt wird,
rein nur bei der Abfrage volatile machen.  Also statt:
#include <avr/io.h>

extern uint8_t flag;

void
doit(void)
{
        PORTB = 42;
        while (!flag)    // funktioniert so nicht!
                /* wait */;
        PORTB = 0x2a;
}
#include <avr/io.h>

extern uint8_t flag;

void
doit(void)
{
        PORTB = 42;
        while (!*(volatile uint8_t *)&flag) // das klappt
                /* wait */;
        PORTB = 0x2a;
}

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.