konvertierungs - verständnissproblem



  • hi,
    ich habe hier
    http://pronix.linuxdelta.de/C/standard_C/c_programmierung_27_3.shtml
    diese funktion

    char convert(char *hex)
    {
       char ascii;
       /* erster Hexawert */
       ascii =
       (hex[0] >= 'A' ? ((hex[0] & 0xdf) - 'A')+10 : (hex[0] - '0'));
    
       ascii <<= 4; /* Bitverschiebung schneller als ascii*=16 */
       /* zweiter Hexawert */
       ascii +=
       (hex[1] >= 'A' ? ((hex[1] & 0xdf) - 'A')+10 : (hex[1] - '0'));
       return ascii;
    }
    

    gefunden. ich weiß zwar, was die funktion macht aber ich verstehe nicht, wieso
    hier das 0xdf benutzt wird. leider erwähnt der autor das auch nicht. ist denn
    diese und-verknüpfung überhaupt nötig? 😕



  • Helfe bitte mal ein anderer dem JW Pfuschgeschädigtem.



  • In der ASCII-Kodierung ist Großbuchstabe + 32 = entsprechender Kleinbuchstabe. Da 32 eine Zweierpotenz ist, unterscheiden sich der Groß- und Kleinbuchstabe dementsprechend nur durch ein Bit (0x20), und ~0x20 = 0xdf. hex[0] & 0xdf ist also (Locales mal beiseitegelassen, die sind hier unerheblich) eine unleserliche Schreibweise für toupper(hex[0]).

    Eine Fehlerbehandlung ist hier nicht implementiert und auch nicht einfach einpflegbar, deswegen verzeih mir die mangelhafte Funktionalität meines hoffentlich lesbareren Ersatzvorschlags:

    char hex_nibble(char xdigit) {
      if(xdigit >= '0' && xdigit <= '9') return xdigit - '0';
      return tolower(xdigit) - 'a' + 10;
    }
    
    char convert(char const *hex) {
      return hex_nibble(hex[0]) << 4 | hex_nibble(hex[1]);
    }
    

    Übrigens ist der Kommentar in

    ascii <<= 4; /* Bitverschiebung schneller als ascii*=16 */
    

    natürlich völliger Blödsinn - jeder respektable Compiler macht daraus genau das Gleiche. Da allerdings im Fall eines vorzeichenbehafteten char-Typen mit Overflows gerechnet werden muss, liefert ascii *= 16 streng genommen ein unspezifiziertes Ergebnis. Es gibt heute nicht mehr viele Maschinen, auf denen negative Zahlen anders als durch das Zweierkomplement dargestellt werden, aber es kostet ja nichts, das richtig zu machen.



  • ah, das war ja mal recht interessant mit der toupper geschichte, danke.



  • Es ist wichtig, anzumerken, dass das nur mit ASCII und verwandten Kodierungen funktioniert. Auf einigen IBM-Mainframes, wo noch EBCDIC zum Einsatz kommt, fliegt der Bitmasken-Ansatz in der gegebenen Form auseinander (dort ist Kleinbuchstabe + 64 = Großbuchstabe), und für breitere bzw. variabel breite Kodierungen wie UCS-* oder UTF-* braucht man sowieso ganz andere Herangehensweisen.


Anmelden zum Antworten