Hallo zusammen, brauche mal wieder Eure Unterstützung: Folgendes gilt: ---------------------- const unsigned char Gleisbild1[11616] PROGMEM = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, ...... } prog_uint8_t *PtrGleisbild; void Map_Pixel( ... , const prog_uint8_t xyz[], ...); PtrGleisbild = &Gleisbild1[0]; // dies ist Zeile 209 !!!!!! Map_Pixel (... , PtrGleisbild, ...); ----------------------- Und nun meckert GCC mit WARNING ../test.c:209: warning: assignment discards qualifiers from pointer target type Programm läuft aber prima - wie bitte bekomme ich WARNING weg ? Vielen Dank im voraus und Grüsse
Nun, PtrGleisbild ist ein Pointer auf einen prog_uint8_t während Gleisbild vom Typ const unsigned char ist, was aus Sicht des Compilers nicht dasselbe ist. Die Warnung an sich bezieht sich eigentlich nur auf den Typqualifizierer const , den Du mit der Zuweisung "wegschmeißt" (engl. to discard -> wegwerfen). Entweder lässt Du die Warnung ne Warnung sein (sie ist, wie Du selber schon gemerkt hast, kein Fehler) oder Du passt die Typen an. Gibt es einen Grund, Gleisbild nicht als prog_uint8_t zu deklarieren? Du könntest natürlich auch den Pointer als Pointer auf const deklarieren. Viele Wege führen nach Rom...
sehr ricchtig was gcc macht ich meine dass sollte sogar ein error sein int c=5; const int * pc = &c; // eine freiwillige einschräkung const int c=5; const int * pc = &c; // notwenigkeit du solltest dich mit constness in c++ auseinandersetzen dann verstehst du warum zb folgendes auch nicht geht int ** feld; const int ** pfeld = feld; // error nun als tipp const int const pfeld = feld; // geht wieder const int const const pfeld = feld; // auch was ich nicht weiss ist, ob die tatsache dass feld im eeprom liegt, eine zusätztliche deklaration für den zeiger erfordet. damit der compiler nicht denkt die variavle liege in sram. grüsse, daniel
const int const pfeld = feld; // geht wieder const int const const pfeld = feld; // auch die hervorhebungsfunktion mit WORT hat den code verfälscht ;)
daniel wrote: > sehr ricchtig was gcc macht > ich meine dass sollte sogar ein error sein Im Prinzip kann dabei aber nicht viel passieren, weshalb ne Warnung eigentlich ausreichend ist. In 99% der Fälle dürfte hier das Programm das machen, was der Programmierer erreichen wollte... > du solltest dich mit constness in c++ auseinandersetzen > dann verstehst du warum zb folgendes auch nicht geht Nun, zunächst mal ist das C und kein C++, aber ansonsten stimme ich Dir zu. > was ich nicht weiss ist, ob die tatsache dass > feld im eeprom liegt, eine zusätztliche deklaration > für den zeiger erfordet. damit der compiler nicht denkt > die variavle liege in sram. Wieso EEPROM? Es geht hier ums Flash (Programmspeicher). Und durch das Attribut PROGMEM wird dem Compiler auch mitgeteilt, dass Variable und Zeiger im Flash liegen (der Spezial-Datentyp prog_uint8_t enthält das Attribut bereits). > die hervorhebungsfunktion mit WORT hat > den code verfälscht ;) Und warum formatierst Du den Code nicht gleich vernünftig als C-Code? Dann wird auch nix verfälscht...
Danke an alle, soweit ich es nun verstanden habe, ist "const" (und nicht der mismatch von "uint8" mit "char") die Ursache. Nun sind die Daten im Flash aber sowieso const - oder habe ich da etwas nicht verstanden ? Das weiss der Compiler doch - oder ? Wenn ich nun "const" weglasse, dann sage ich doch implizit, dass ich den Speicherbereich als RAM ansehe - oder sehe ich die Dinge zu einfach ??? Grüsse
Wenn du dem Compiler sagst, dass der Wert und die Adresse konstant ist, dann weiss er es. Ich würde es wie folgt machen, so sollte es konsistent sein:
1 | #include <pgmspace.h> |
2 | |
3 | prog_uint8_t Gleisbild1[11616] = |
4 | {
|
5 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
6 | 0xFF, 0xFF, 0xFF, 0xFF, ...... |
7 | };
|
8 | |
9 | prog_uint8_t* PtrGleisbild; |
10 | |
11 | void
|
12 | Map_Pixel( ... , prog_uint8_t* xyz, ...); |
13 | |
14 | // ...
|
15 | |
16 | PtrGleisbild = &Gleisbild1[0]; |
17 | |
18 | // ...
|
19 | |
20 | Map_Pixel (... , PtrGleisbild, ...); |
21 | |
22 | // ...
|
Noch ein kleiner Tip am Rande. In einem anderen Beitrag hast du geschrieben, dass du den Mega128 als Target nutzt. Nun sind deine Tables im Programmspeicher schon recht groß, du solltest aufpassen, dass ein zusammenhängendes Table nicht "auf der Grenze" 64KiB liegt. Da kann es Probleme geben wenn man das nicht beachtet.
die ??? wrote: > Noch ein kleiner Tip am Rande. In einem anderen Beitrag hast du > geschrieben, dass du den Mega128 als Target nutzt. Nun sind deine Tables > im Programmspeicher schon recht groß, du solltest aufpassen, dass ein > zusammenhängendes Table nicht "auf der Grenze" 64KiB liegt. Da kann es > Probleme geben wenn man das nicht beachtet. Au, da sprichst Du ein interesantes Theam an: Ich habe 1. in Erinnerung, dass dies GCC abhängig ist und mit der neuesten Version das Problem nicht mehr aktuell ist ? Kann ich kaum glauben - habe ich etwas falsch verstanden ? 2. Welche Einflussmöglichkeiten habe ich denn (aus Studio4 heraus), den Speicherbereich in den 2. 64k Block zu moven? Dass es für diesen Berich extra Lesebefehle (Zugriffsbefehle) gibt, habe ich gelernt. 3. Was mache ich denn bei einem AT256 ? Da gibt es dann ja 4 * 64k Blöcke ... Kann ich nur 2 davon nutzen ? Sicherlich silly Questions, aber dieses Theam ist für mich Neuland. Grüsse
die ??? wrote: > Wenn du dem Compiler sagst, dass der Wert und die Adresse konstant ist, > dann weiss er es. Ich würde es wie folgt machen, so sollte es konsistent > sein: > > >
1 | > #include <pgmspace.h> |
2 | >
|
3 | > prog_uint8_t Gleisbild1[11616] = |
4 | > { |
5 | > 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, |
6 | > 0xFF, |
7 | > 0xFF, 0xFF, 0xFF, 0xFF, ...... |
8 | > }; |
9 | >
|
10 | > prog_uint8_t* PtrGleisbild; |
11 | >
|
12 | > void |
13 | > Map_Pixel( ... , prog_uint8_t* xyz, ...); |
14 | >
|
15 | > // ... |
16 | >
|
17 | > PtrGleisbild = &Gleisbild1[0]; |
18 | >
|
19 | > // ... |
20 | >
|
21 | > Map_Pixel (... , PtrGleisbild, ...); |
22 | >
|
23 | > // ... |
24 | >
|
Sorry, dass ich mich erst jetzt wieder melde - habe Deinen Rat befolgt, jetzt ist alles o.k. Aaaaaber - worin liegt denn nun der Unterschied ??? Im Flash liegen für den Compiler doch immer nur Konstanten, da könnte man nun doch sagen, deswegen muss das 'const' unbedingt dahin, andererseits könnte man argumentieren, das 'const' kann man weglassen, es gibt ja keine andere Möglichkeit. Was ist nun richtig ? Und daraus die eigentliche Frage: Wann nehme ich denn nun das 'const' und wann nicht (im Flash natürlich) ? Hintergrund der Frage: Ich benutze einen wizzard, der aus dem gif Bild diese Noation mit 'const' macht ... und der Programmierer scheint mir nicht ganz doooof (kein kleiner Dummer ;-)) zu sein! Nun nehme ich es also heraus, damit ggc Ruhe gibt - und mit meinem restlichen Code logisch matcht - wo ist die Gefahr ? Sorry, dass ich so nerve, aber ich will es verstehen. Grüsse
Ein 'const' bewirkt zunaechst nur, dass eine Variable schreibegschuetzt wird, also nur initialisiert, aber nicht mehr veraendert werden kann. Sie liegt aber weiter im RAM. prog_uint8_t Gleisbild1... erzeugt ein Array im Flash (was zwar implizit schreibgeschuetzt und effektiv, aber nicht explizit const ist). ("prog_uint8_t" expandiert zu "uint8_t PROGMEM" const unsigned char Gleisbild1[11616] PROGMEM = ... erzeugt hingegen ein Array im Flash, das explizit const ist. Entspricht also "const prog_uint8_t Gleisbild1" prog_uint8_t* PtrGleisbild; erzeugt hingegen einen Pointer auf ein prog_uint8_t, also ein uint8_t PROGMEM, der weder konstant ist, noch selber im Flash liegt und dessen Zieltyp auch nicht const ist (auch wenn er im Flash liegt und damit nicht ueberschreibbar ist). Was die Typpruefung angeht (const oder nicht etc.) ist das das Progmem-Segment naemlich zunaechst einmal ein Segment wie jedes andere, wie _bss, _data oder wie auch immer. Das bei der Codegenerierung dann spaeter ein spezieller Zugriffsbefehl noetig ist, ist zunaechst irrelevant. Daher der Fehler: Deine Initialisierung intitialisiert einen Pointer auf einen "uint8_t" mit einem pointer auf einen "const uint8_t", was fue rdie weitere Nutzung des Pointer die "const"-Eigenschaft des urspruenglichen Arrays aufhebt. Daher die Warnung. Solange man im Code dann nicht schreibend auf das Ziel des Pointers zugreift, macht es keinen Unterschied. Der Compiler wuerde die Unmoeglichkeit aber u.U. nicht merken, da der spaeter verwendete Pointer ja nciht auf ein const-Element zeigt. "PtrGleisbild[0][0]=7" waere also eine gueltige Anweisung, nur der Assembler/Linker bekommt spaeter Probleme und man weiss nicht, warum. Pointer sind ein kompliziertes Feld. Pointer auf Arrays umso mehr, Pointer auf Arrays von Pointern ganz besonders. Und wenn 'const' dazukommt, wird es noch komplexer. Von Attributen ganz zu schweigen. Denn ist es nun ein constanter Pointer auf einen veraenderbaren Inhalt oder ein veraenderbarer Pointer auf constante Inhalte? oder beides? Die Verwendung von Macros, die ihrerseits Attribute oder Qualifier hinzufuegen, macht die Sache noch komplizierter. Am Besten, man sagt dem Compiler, er soll den Praeprozessor-Output nicht loeschen und schaut sich dann an, was der Praeprozessor nach Aufloesen aller Macros ausgespuckt hat. Das sieht zwar nicht schoen aus, aber es ist das, was der Compiler sieht und nicht das, was man glaubt, was er sieht.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.