- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 24

Thema: explizite Typumwandlung

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076

    explizite Typumwandlung

    Guten Morgen,
    ich habe eine, oder sind es mehrere Fragen zur Typumwandlung. Zunächst ganz einfach:

    Code:
    Warum funktioniert folgender Code nicht wie erhofft ?
    
    int* p = (char*)1000;   /* p zeigt nun auf die Speicherstelle 1000 */
    (char*)p++;
    
    p zeigt nun auf 1004 leider nicht wie erwartet auf 1001. Das "Casten" wurde anscheinend völlig ignoriert ?
    
    und das Folgende meckert der Compiler komplett an:
    void* p = (void*)1000;  
    
    (char*)p++;   /* expression must be a pointer to a complete object type */
    
    
    Erklärung was ich machen möchte:
    Eine universelle Funktion schreiben, der ich lediglich eine Adresse und eine Anzahl übergebe um Daten mittels RS232 zu übertragen.
    VOID möchte ich benutzen, damit ich später keine explizite Typwandlung mehr benötige. Also einen Pointer auf irgendwas übergeben kann.
    So soll es aussehen:
    
    void uart_putc(char c)
    {
        /* ....... */
    }
    
    void uart_send(void* data, unsigned int size)
    {
       while(size--)
          uart_putc(*(char*)data++);   /* hier gibt es das Problem */
    }
    
    
    Ich war ja schon fleißig und habe natürlich schon einige Versionen ausprobiert und hinbekommen
    So geht es zum Beispiel:
    
    void uart_send(void* data, unsigned int size)
    { char*p=data;
    
       while(size--)
          uart_putc(*p++);
    }
    
    aber wozu die unnötige, lokale Zwischenvariable "p" , ich hab doch schon meinen Pointer "data" den muss ich doch Byteweise hochzählen können.
    Ich bedanke mich schon im voraus für (meinen neuen Lerneffekt) bzw. Eure Hilfe.
    Siro

  2. #2
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.842
    Versuch mal
    ( (char*)p ) ++;
    ich hab's aber nicht probiert, also ohne gewähr

    Gedanke dahinter:
    (char*)p++ heisst ja, er soll das, was bei p++ rauskommt, als char* interpretieren.

    Ich mach das meist so:
    p = (int*) ((int)p + 1);
    geht aber sicher eleganter, ich bin aber nicht an Forschung interessiert , hauptsache, es funzt
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  3. #3
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    39
    Beiträge
    3.416
    also wie PickNick und auch ich das sehen, ist das nur logisch, es wird ERST p++ ausgehführt und DANACH der cast auf char-pointer!
    PickNicks Lösung musst du verwenden, dann sollte es gehen!

    Der 2te fehler ist genau das gleiche Problem, er kann einen void-pointer nicht inkrementieren, weil der Cast erst NACH der Operation durchgeführt werden würde!

    @PickNick deine 2te Lösung sieht gruselig aus, du castest die Adresse in einen Zahlenwert um, manipulierst ihn udn dann wieder zu einem Pointer ... (da schüttelt es mich XD)

    PS: ich würde statt einem char* lieber einen byte* oder einen uint8* verwenden ... ist jetzt nur ne stilsache, aber char kann auch als unicode interpretiert werden und der hat 16bit!

    muss mich selber zusammenreissen nicht immer char zu schreiben


    Code:
    void uart_send(void* data, unsigned int size) {    
       while(size--)       
          uart_putc(*(((byte*)data)++));   /* erst casten, dann inkrementen, dann  dereferenzieren */ 
    } 
    
    void uart_send(void* data, unsigned int size, unsigned int repeat = 1 ) {    //keine Ahnung ob der WinAVR optionale Parameter unterstützt aber macht es noch multifunktionaler!
       while(repeat--) 
       {
          for(unsigned int i = 0; i < size; i++)       
             uart_putc(*(((byte*)data)++));   /* erst casten, dann inkrementen, dann  dereferenzieren */ 
       }
    }
    So viel Klammer muss halt sein wenn man sicher gehen will dass der compiler es auch versteht!
    Geändert von Ceos (06.10.2011 um 12:29 Uhr)
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  4. #4
    Super-Moderator Robotik Visionär Avatar von PicNick
    Registriert seit
    23.11.2004
    Ort
    Wien
    Beiträge
    6.842
    Wegen Grusel und Graus : Das rumcasten erzeugt ja keinen Code, sondern zwingt den Compiler zu anderen MaschinenInstruktionen. Insofern bleibt nur die schaurige Optik in der Source, da geb' ich dir schon recht.

    Mir persönlich graust mehr, wenn einer elegant die gauss'sche Osterberechnung in ein Statement quetscht
    mfg robert
    Wer glaubt zu wissen, muß wissen, er glaubt.

  5. #5
    Erfahrener Benutzer Roboter Experte Avatar von sternst
    Registriert seit
    07.07.2008
    Beiträge
    672
    Zitat Zitat von Ceos
    PS: ich würde statt einem char* lieber einen byte* oder einen uint8* verwenden ... ist jetzt nur ne stilsache, aber char kann auch als unicode interpretiert werden und der hat 16bit!
    char ist laut Definition der kleinste Typ in C (sizeof(char) ist immer 1). Wenn ein char 16 Bit hat (was durchaus sein kann), dann gibt es in der Umgebung ein uint8_t schlicht nicht. Und auch byte (was immer das konkret sein mag) kann dann nicht kleiner als 16 Bit sein.
    MfG
    Stefan

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Ein bischen weiter geholfen habt Ihr mir ja, aber Eure Lösungen scheinen nicht so zu funktionieren wie ich es wollte.

    Zu PicNick:

    p = (int*) ((int)p + 1);

    erhöht bei mir den Zeiger um 4, hab ich grad mal ausprobiert.


    Zu Ceos:

    uart_putc(*(((byte*)data)++));

    gibt bei mir einen Fehler: expression must be a modifiable lvalue


    Zumindest hab ich jetzt verstanden, daß der Compiler anscheinend von rechts nach links auswertet.
    Dann leuchtet mir ein, daß mein Lösungsweg auch nicht funktionieren konnte.


    Lösung steht also noch aus......Danke Euch schonmal für die Anteilnahme

    Siro

  7. #7
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Zitat Zitat von Siro Beitrag anzeigen

    Code:
    void uart_putc(char c)
    {
        /* ....... */
    }
    
    void uart_send(void* data, unsigned int size)
    {
       while(size--)
          uart_putc(*(char*)data++);   /* hier gibt es das Problem */
    }
    Was mir hier nicht klar ist:

    wozu ist eine Funktion gut, die Daten vom Typ "weißnichtsogenau", und das ist void, in eine andere Funktion stopft, die nur mit chars umgehen kann. Sollte data mal auf ints oder floats zeigen, kommt etweder Müll raus, oder es crasht. Und die Verwendung von void-Pointern führt nur dazu, daß einem der Compiler nicht mehr helfen kann, Fehler zu vermeiden.

    Es muß also heißen: uart_send(char* data, ... , und in Zukunft für jeden void* 5€ in die Kaffekasse (oder ersatzweise eine schriftliche Begründung von mindestens einer Seite, warum so etwas aus Gründen der Programmlogik wirklich nötig ist )!

    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    zu PicNick
    Sorry, ich muss mich korrigieren, deine Zeile

    p = (int*) ((int)p + 1);

    funktioniert wirklich. Erhöht den Zeiger um 1 und nicht um 4.
    Hast Du völlig recht.


    zu Klebwax:

    wie soll man denn sonst eine universelle function schreiben ?
    ich möchte verschiedene Datentypen, Strukturen und ähnliches
    senden. Das Casten übernimmt bei mir die Funktion, ich brauche mich darum
    nicht mehr zu kümmern. Ich übergebe nur noch die Adresse und die Anzahl Bytes.

    int xx;

    struct
    char a,b,c,d;
    int e,f,g;&lt;
    } st;


    und zudem finde ich daß:

    uart_send(&xx,sizeof(xx));
    uart_send(&st,sizeof(st));

    besser aussieht als:

    uart_send((char*)&xx,sizeof(xx));
    uart_send((char*)&st,sizeof(st));

    aber das ist sicher Geschmackssache. Funktionieren tut natürlich beides. Was die Sicherheit angeht,
    denke ich mal, nehmen sich beide Varianten nichts.
    anbei meine 5,-- Euro...

    Habt noch ein schönes Wochenende.

    Siro

  9. #9
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Zitat Zitat von Siro Beitrag anzeigen
    wie soll man denn sonst eine universelle function schreiben ?
    ich möchte verschiedene Datentypen, Strukturen und ähnliches
    senden. Das Casten übernimmt bei mir die Funktion, ich brauche mich darum
    nicht mehr zu kümmern. Ich übergebe nur noch die Adresse und die Anzahl Bytes.

    int xx;

    struct
    char a,b,c,d;
    int e,f,g;<
    } st;


    und zudem finde ich daß:

    uart_send(&xx,sizeof(xx));
    uart_send(&st,sizeof(st));

    besser aussieht als:

    uart_send((char*)&xx,sizeof(xx));
    uart_send((char*)&st,sizeof(st));

    aber das ist sicher Geschmackssache. Funktionieren tut natürlich beides. Was die Sicherheit angeht,
    denke ich mal, nehmen sich beide Varianten nichts.
    anbei meine 5,-- Euro...
    Ich frag jetzt mal garnicht, ob du das ernst meinst. Was du willst, geht garnicht. Man kann weder ein Int noch eine Struktur einach so über die serielle Schnittstelle versenden. Dein Compiler hat schon gewußt, warum er deinen Code nicht bearbeiten wollte, und du ihn erst mit void* und casts mundtot machen musstest.

    Die 5€ kannst du behalten. Leg noch was drauf und kauf dir ein Buch über C und lerne. Und mach dir mal Gedanken über Strukturen, gepackt und ungepackt, auf verschiedenen CPUs mit 8 bis 64 Bit Wortbreite sowie Big und Little Endian und dann lerne was über robusten portablen Code und gewöhne dir einen solchen Stil an.


    MfG Klebwax
    Strom fließt auch durch krumme Drähte !

  10. #10
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Ich muss hier sicher keine Rechenschaft ablegen, aber zu Klebwax:
    ich möchte die Bytes so herausschicken, wie sie im Speicher stehen.
    Ob sie gepackt sind oder im Intel oder Motorola Format vorliegen ist in MEINEM Falle völlig unwichtig,
    Das ist lediglich ein Hexdump den ich zu Testzwecken herausschicke um SOFTWAREFEHLER AUFZUDECKEN.
    Deshalb finde ich deine voreilige Beurteilung unberechtigt negativ, satt kreativ...

    Dein Satz:
    Was du willst, geht garnicht. Man kann weder ein Int noch eine Struktur einach so über die serielle Schnittstelle versenden.
    ist in meinem Falle eine Falschaussage, denn es funktioniert ja einwandfrei.
    Siro

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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

Solar Speicher und Akkus Tests