Verständnisprobleme beim Mustercode



  • Hi, ich bitte nochmals um NAchhilfe. Folgenden Code habe ich einem Sample-( c-)Code entnommen:

    #define BTI_FAR
       typedef unsigned char         BTI_BYTE;
       typedef long                  BTI_LONG;
    
       BTI_BYTE m_keyBuf[255];
    
       BTI_LONG personID;
       personID = 263512477;    
       *(BTI_LONG BTI_FAR *)&m_keyBuf[0] = personID;
       /* ==
        *(long *)&keyBuf[0] = personID; 
       */
    

    Interpretier ich das so richtig?
    -m_keyBuf ist ein Speicherbereich, in dem 255 unsigend char gespeichert werden können
    -der Zahlen wert von &m_keyBuf[0] ist die Addresse des erste unsigned char, und damit der Beginn der 255 Zeichen
    - der erste stern sagt mir, daß ich diese adresse als Pointer zu verstehen habe: ich schaue nach, was in &m_keyBuf steht, und dieser Wert zeigt auf die Adresse der eigentlichen Nutzdaten. Gehe ich dorthin finde ich den zu verwendenden Wert: personId.
    - (long 😉 sagt mir den Typ, den ich letztlich zu erwarten habe, ein long.

    Vorausgesetzt ich habe das richtig verstanden, bekomme ich aber die Lösung der nächsten Aufgabe nicht hin:
    <b>m_keyBuf soll sein cSuchbegriff</b>
    das string.c_str() ein const char * Array liefert dachte ich an

    reinterpret_cast< const char *>(m_keyBuf) = cSuchBegriff.c_str();
    

    doch auch das geht nicht



  • HannsW schrieb:

    reinterpret_cast< const char *>(m_keyBuf) = cSuchBegriff.c_str();
    

    Das geht so nicht, denn du musst den rechten Typ anpassen, damit er in den linken Typ passt. Nicht umgekehrt.

    -m_keyBuf ist ein Speicherbereich, in dem 255 unsigend char gespeichert werden können
    -der Zahlen wert von &m_keyBuf[0] ist die Addresse des erste unsigned char, und damit der Beginn der 255 Zeichen

    Korrekt.

    BTI_BYTE *p1 = &m_keyBuf[0];
    BTI_BYTE *p2 = m_keyBuf;
    Tun das gleiche.
    

    (long 😉 sagt mir den Typ, den ich letztlich zu erwarten habe, ein long.

    Nein, einen Pointer auf long. Wenn du den derefernzierst...

    long l;
    l = *(long*)p;
    

    hast du ein long.



  • SeppSchrot schrieb:

    BTI_BYTE *p1 = &m_keyBuf[0];
    BTI_BYTE *p2 = m_keyBuf;
    Tun das gleiche.
    

    das Ampersand bei p2 brauche ich nciht, weil vom array immer die Anfangs-Adresse
    genommen wird- das ist eindeutig- bei p1 könnten es ja 255 mögliche Adressen sein ??

    (long 😉 sagt mir den Typ, den ich letztlich zu erwarten habe, ein long.

    Nein, einen Pointer auf long. Wenn du den derefernzierst...

    Hatte ich eigentlich mit letztlich gemeint: Folge ich der Pointer-Kette, lande ich bei einem long

    links habe ich einen pointer auf unsigned char, und rechts liefert mir einen pointer auf ein char, nicht veränderbar ?

    Dann müsste doch dies klappen

    BTI_BYTE *pkeyBuf ;
            pkeyBuf = m_keyBuf;
            *pkeyBuf = reinterpret_cast<BTI_BYTE *>(cSuchBegriff.c_str());
    /
    

    Damit erhalte ich beim g++ unter linux diese Meldung

    g++ -c -Wall btrieveClass.cc
    btrieveClass.cc: In member function `bool btrieve::seek(std::basic_string<char, 
       std::char_traits<char>, std::allocator<char> >, bool)':
    btrieveClass.cc:253: error: reinterpret_cast from `const char*' to `BTI_BYTE*' 
       casts away const (or volatile)
    btrieveClass.cc:253: error: invalid conversion from `BTI_BYTE*' to `unsigned 
       char'
    

    PUUUHH 😕



  • HannsW schrieb:

    das Ampersand bei p2 brauche ich nciht, weil vom array immer die Anfangs-Adresse
    genommen wird- das ist eindeutig- bei p1 könnten es ja 255 mögliche Adressen sein ??

    Ja. Durch den IndexOperator[] wird ein Objekt zurückgeliefert, das durch den Adressoperator & wieder einen Pointer auf dieses Objekt liefert.

    Dann müsste doch dies klappen

    BTI_BYTE *pkeyBuf ;
            pkeyBuf = m_keyBuf;
            *pkeyBuf = reinterpret_cast<BTI_BYTE *>(cSuchBegriff.c_str());
    /
    

    Das klappt nicht aus 2 Gründen.
    1. string::c_str() liefert einen Pointer auf const char zurück.
    Das willst du zu einem nicht konstanten u char umwandeln. (Also beschreibbar machen, obwohl es doch konstant ist.)
    Deswegen gibt es eine Warnung (verbieten kann es der Compiler nicht), die durch die -wall Option als Fehler angekreidet wird. Gut so.

    2. Du weist diesen Pointer nicht pkeyBuf zu, sondern dem Objekt, auf das der Pointer zeigt (* ganz am Anfang).

    PUUUHH 😕

    Jo, da musste jeder mal durch.
    Vielleicht solltest du es ersteinmal ohne typedefs durchprobieren, bis du klarer siehst.



  • SeppSchrot schrieb:

    PUUUHH 😕

    Jo, da musste jeder mal durch.
    Vielleicht solltest du es ersteinmal ohne typedefs durchprobieren, bis du klarer siehst.

    Das mit den Typedefs ist glaub ich nicht das Problem für mich. Ich habs mir im Quellcode erst einmal zusätzlich als Kommentar "Übersetzt" dazugeschrieben.

    ich weiß,
    -daß meine API-Function als paramtere u.a ein Array aus 255 u char erwartet.
    -daß ich meinen Wert in einem string habe
    -daß string.c_str() ein **const char *** liefert, daß ich nicht zuweisen kann;
    -daß ich den string nicht casten kann
    -daß ich bals irre werde...
    😃 eventuell einen klitzekleinen tipp in die richtige Denkrichtung 😃

    ich habs mal so probiert

    int status; 
            for ( status = 0; status < (int)cSuchBegriff.size(); status ++){
                    m_keyBuf[status]= (BTI_BYTE)(cSuchBegriff.c_str()[status]);
            }
    

    Ich kann da noch Überläufe bekommen, wenn cSuchBegriff länger als 255 ist,
    aber das schluckt der compiler zumindest.

    Sollte es das gewesen sein????



  • strcpy oder string::copy
    sind auch was Feines.

    http://www.cppreference.com/



  • SeppSchrot schrieb:

    strcpy oder string::copy
    sind auch was Feines.

    http://www.cppreference.com/

    in der Tat, doch nützen mir die nichts, wenn mein Ziel ab Pos z.B. 5 10 neue Zeichen erhalten soll.

    Wenn es dafür auch was gäbe!
    mit str.copy() habe ich es leider nicht geschafft.



  • HannsW schrieb:

    in der Tat, doch nützen mir die nichts, wenn mein Ziel ab Pos z.B. 5 10 neue Zeichen erhalten soll.

    Versteh ich nicht.



  • naj, eigenlich muss ich mein u char Array aus verschiedenen Strings zusammenbasteln:

    datenbufffer setzen
    void btrieve::setDatenBuffer (int start,int len,std::string neuerWert){
            int i;
            for (i = start; i<= len; i++){
                    m_dataBuf[i] = (BTI_BYTE)neuerWert.c_str()[i];
            }
    //      m_dataBuf.replace (start,len,reinterpret_cast<const char *>(neuerWert));
    }
    

    wobei die aufrufende Function alle längenprüfungen vorgenommen hat:

    void aliasArzt::setCode (std::string neuerWert){  //ist btrieveClass
            // Arzt auf richtige Länge bringen
            if( neuerWert.size() > 5){
                    neuerWert = neuerWert.substr(1,5);
            }
            // falls zu kurz
            while ( neuerWert.size() < 5){
                    neuerWert += " ";
            }
            // und in den Buffer schreiben
            setDatenBuffer(1,5,neuerWert);
    }
    

    in meinem m_dataBuf müssen bei der Übergabe meine Datenfelder stehen: z.B
    1111111111222222222222222333 // der rest ist 0x0
    i.e string1 mit 10char, 2 mit 15 und 3 mit 3

    Nun könnte ich mir ja mit str.append() einen neuen "Gesamt"string bauen, aber dann habe ich wieder das Pro....moment 👍
    so könnte es gehen:
    meine Datenfelder (strings) werden geändert, vor dem Update baue ich nen neuen Hilfsstring mit append() zusammen, und den mit .copy() ins char Array.

    Werde ich versuchen
    Danke für die Anregung
    Hanns



  • Und sprintf hast du schon mal angeschaut?


Anmelden zum Antworten