Forum: Compiler & IDEs memcpy-Warnung


von Owen S. (senmeis)


Lesenswert?

Hi,

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

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

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

Ist es schlimm?

Gruss
Senmeis

von (prx) A. K. (prx)


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);

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

A. K. wrote:

> Kannst du vermeiden mit:

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

von (prx) A. K. (prx)


Lesenswert?

Fällt dir was besseres ein?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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.

von (prx) A. K. (prx)


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.

von (prx) A. K. (prx)


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.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


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:
1
#include <avr/io.h>
2
3
extern uint8_t flag;
4
5
void
6
doit(void)
7
{
8
        PORTB = 42;
9
        while (!flag)    // funktioniert so nicht!
10
                /* wait */;
11
        PORTB = 0x2a;
12
}
1
#include <avr/io.h>
2
3
extern uint8_t flag;
4
5
void
6
doit(void)
7
{
8
        PORTB = 42;
9
        while (!*(volatile uint8_t *)&flag) // das klappt
10
                /* wait */;
11
        PORTB = 0x2a;
12
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.