- 12V Akku mit 280 Ah bauen         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 11

Thema: C18: Warning [2054] suspicious pointer conversion

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    08.06.2010
    Beiträge
    26

    C18: Warning [2054] suspicious pointer conversion

    Anzeige

    Praxistest und DIY Projekte
    Warum kommt dieser Fehler/Warnung (PIC18F14K50)?

    Mit Ampersand kommt die gleiche Warnung: &tmrGATEcounter.

    Danke

    Warning [2054] suspicious pointer conversion


    Code:
    static volatile unsigned short tmrGATEcounter;
    
    void ReadEEdata8(unsigned char *dest, unsigned char addr) {
      	EECON1bits.CFGS = 0;     //0: program memory / EEPROM memory 
    	EECON1bits.EEPGD = 0;	 //0: EEPROM memory
    	EEADR = addr;            //Adresse laden Low -Byte.
    	EEADRH = 0;              //Adresse laden High-Byte.
    	EECON1bits.RD = 1;       //Lesezyklus einleiten.
    	*dest = EEDATA;          //EEPROM-Daten => Ziel-Variable.
    }
    
    void ReadEEdata16(unsigned char *dest, unsigned char addr) {
    	unsigned char *p = (unsigned char *)dest;
    	ReadEEdata8(p++, addr++);
    	ReadEEdata8(p, addr);
    
    //-------------------------------------------------------------
    
    void InitVars (void) {
        ReadEEdata16 (tmrGATEcounter, 2);   //Time aus EEPROM laden.
    }

  2. #2
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    06.02.2005
    Ort
    Hamburg
    Alter
    38
    Beiträge
    4.255
    Deine Funktion will einen Pointer auf unsigned char. tmrGATEcounter ist aber ein unsigned short. Sind die bei deinem Compiler gleichgroß? (Besser: die Typen aus stdint.h verwenden, also z.B. uint8_t und uint16_t).

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    08.06.2010
    Beiträge
    26
    Sorry vergessen, C18 verwende ich.

    Spielt keine Rolle, ob das char oder short ist, der Fehler bleibt bestehen. Ich sehe da auch keinen rechten Sinn drin, denn ein Pointer ist 16 Bit lang, egal welcher Typ übergeben wird. Würde ich jedenfalls mal denken.

  4. #4
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    06.02.2005
    Ort
    Hamburg
    Alter
    38
    Beiträge
    4.255
    Auf jeden Fall muss das & verwendet werden, denn du übergibst die Adresse und nicht den Wert. Wenn dann die Datentypen übereinstimmen, sollte die Warnung eigentlich verschwinden.
    Und außerdem kannst du dir das p in der Funktion sparen und direkt mit dest arbeiten.

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    08.06.2010
    Beiträge
    26
    Hab's jetzt so geändert, aber jetzt kommt:

    Warning [2066] type qualifier mismatch in assignment

    Code:
    static volatile unsigned short tmrGATEcounter;
    
    void ReadEEdata16(unsigned short *dest, unsigned char addr) {
    	unsigned char *p = (unsigned char *)dest;
    	ReadEEdata8(p++, addr++);
    	ReadEEdata8(p, addr);
    }
    
    void InitVars (void) {
        ReadEEdata16 (&tmrGATEcounter, 2); //<- hier kommt die Warnung.
    }
    Komisch, wenn ich speichere, dann Make mache, dann kommt die oben genannte Warnung. Compiliere ich gleich nochmal, ohne speichern, dann sagt er das alles hervorragend ist, also, Build Success.

    Wenn ich aber "Build All" mache kommt die Warnung bei jeder Compilation.

    Wenn hier letztlich auch keiner eine Ahnung hat, dann probiere ich es mal mit einem struct und union.

  6. #6
    Neuer Benutzer Öfters hier
    Registriert seit
    08.06.2010
    Beiträge
    26
    Habs mal so probiert, aber gleiche Warnung (Warning [2054] suspicious pointer conversion):

    Code:
    static volatile union _tmrGATEcounter {
        unsigned int LH;
        struct {
            char L;
            char H;
        };
    } tmrGATEcounter;
    
    void ReadEEdata8(unsigned char *dest, unsigned char addr) {
      	EECON1bits.CFGS = 0;     //0: program memory / EEPROM memory 
    	EECON1bits.EEPGD = 0;	 //0: EEPROM memory
    	EEADR = addr;            //Adresse laden Low -Byte.
    	EEADRH = 0;              //Adresse laden High-Byte.
    	EECON1bits.RD = 1;       //Lesezyklus einleiten.
    	*dest = EEDATA;          //EEPROM-Daten => Ziel-Variable.
    }
    
    void ReadEEdata16(unsigned char *dest, unsigned char addr) {
    	unsigned char *p = (unsigned char *)dest;
    	ReadEEdata8(p++, addr++);
    	ReadEEdata8(p, addr);
    }
    
    void InitVars (void) {
        ReadEEdata16 (&tmrGATEcounter.L, 2);   //<- Warnung hier !!!
    }
    Ne halt, hab vergessen unsigned vor die char's zu schreiben:

    So geht's dann, keine Warnung mehr:

    Code:
    static volatile union _tmrGATEcounter {
        unsigned int LH;
        struct {
            unsigned char L;
            unsigned char H;
        };
    } tmrGATEcounter;
    
    void ReadEEdata8(unsigned char *dest, unsigned char addr) {
         EECON1bits.CFGS = 0;     //0: program memory / EEPROM memory
       EECON1bits.EEPGD = 0;    //0: EEPROM memory
       EEADR = addr;            //Adresse laden Low -Byte.
       EEADRH = 0;              //Adresse laden High-Byte.
       EECON1bits.RD = 1;       //Lesezyklus einleiten.
       *dest = EEDATA;          //EEPROM-Daten => Ziel-Variable.
    }
    
    void ReadEEdata16(unsigned char *dest, unsigned char addr) {
       unsigned char *p = (unsigned char *)dest;
       ReadEEdata8(p++, addr++);
       ReadEEdata8(p, addr);
    }
    
    void InitVars (void) {
        ReadEEdata16 (&tmrGATEcounter.L, 2);   //<- Warnung hier !!!
    }
    Aber warum geht das aus den oberen Postings nicht? Pointer sind wohl mehr für Strings gedacht.

  7. #7
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    06.02.2005
    Ort
    Hamburg
    Alter
    38
    Beiträge
    4.255
    Es könnte eigentlich nur noch sein, dass der Compiler sich am static stört...

    Dass die Warnung nicht immer erscheint liegt daran, dass der Compiler zunächst prüft, ob die Zwischenergebnisse von letzten Durchlauf noch aktuell sind. Dann werden immer nur die wirklich veränderten Dateien komplett neu übersetzt und vom Linker mit den schon übersetzten Teilen zusammengefügt. Bei größeren Projekten mit viel Code spart das einiges an Zeit.

  8. #8
    Neuer Benutzer Öfters hier
    Registriert seit
    08.06.2010
    Beiträge
    26
    Er stört sich nicht an "static", sondern an "volatile".

    Was volatile exakt bewirkt ist mir jedoch etwas unklar. Ich weiss nur, dass man es verwenden soll, wenn die Variable auch innerhalb von Interrupts Verwendung finden soll.

    Wo da jedoch der tiefere Sinn liegt ist mir unklar.

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    17.08.2009
    Beiträge
    31
    Ok, der Thread ist schon etwas älter, aber da das Thema volatile gerade bei mir aktuell ist, schreibe ich hier mal das, was ich dazu gelernt habe:
    volatile sagt dem Compiler, dass der Wert einer Variable sich jederzeit ändern kann, ohne dass das in der aktuellen Funktion ersichtlich ist. Daher sind zum Beispiel Hardwareregister bei PICs als volatile deklariert. Denn die können sich ja jederzeit ändern, ohne dass die Software diese angefasst hat. Oder wenn man eine globale Variable in einem Interrupt ändert, kann das für die laufende Funktion unbemerkt bleiben.
    Hier ein Beispiel:
    Code:
    volatile int vol_var;
    while (bedingung) {
        int a=vol_var; // Zeile A
        printf("%d\n",vol_var); // Zeile B
    }
    Der C-Compiler würde ohne volatile denken, dass vol_var in der Schleife unverändert bleibt, deswegen den Wert von vol_var nur einmal ermitteln und dann in der Schleife den einmal ermittelten Wert immer wieder verwenden. Mit volatile hingegen wird er vor jeder Benutzung den Wert holen und so immer aktuell wie möglich sein.

    Auf den Code des ersten Posts
    Code:
    static volatile unsigned short tmrGATEcounter;
    void ReadEEdata8(unsigned char *dest, unsigned char addr){...}
    void InitVars (void) {
        ReadEEdata16 (tmrGATEcounter, 2);   //Time aus EEPROM laden.
    }
    bezogen bedeutet das:
    Die Variable tmrGATEcounter ist volatile, unsigned char *dest nicht. Der Compiler würde so (auch bei einem Zeiger) die Information verlieren, dass *dest eine volatile Variable ist.
    Sinnvoll wäre also:
    Code:
    void InitVars (void) {
       unsigned short temp;
       ReadEEdata16 ((unsigned char*)&temp, 2);   //Time aus EEPROM laden.
       tmrGATEcounter = temp;
    }
    Da tmrGATEcounter ja zugewiesen werden soll, reicht es, wenn man einen Zeiger auf eine nicht-volatile Variable übergibt, und dann danach die Zuweisung mit dieser durchführt.

    (Ich hab jetzt mal den Unterschied zw. unsigned char und unsigned short ignoriert.)
    Geändert von Dirk123 (05.05.2011 um 12:51 Uhr)

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    08.06.2010
    Beiträge
    26
    Danke für die Antworten.

    Zumindestens ist mir mal ein Licht aufgegangen was da passiert.

    Der Compiler kopiert also alle Variablen erstmal auf den Stack, bevor sie bearbeitet werden. Wenn eine Variable als volatile gekennzeichnet wurde, dann muss der Compiler zusätzlichen Code einbauen, damit jedes mal geprüft wird, ob die Variable zwischenzeitlich (ausserhalb der aktuell laufenden Routine, z. B. Interrupt-Routine) verändert wurde, bevor er sie weiterbearbeitet werden darf. Nur so kann die Variable auf dem Stack aktuell gehalten werden.

    Volatile bedeutet also: Halte Variable, vor Weiterverarbeitung auf dem Stack, aktuell.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress