C++ String mit hexadezimaler Repräsentation einer Zahl in einen Integer umwandeln (Was tut der Code?)

Dabei seit
Nov. 2007
Beiträge
2.050
#1
Guten Abend zusammen!

Ich bin heute auf ein Codefragment gestoßen, das mir Kopfzerbrechen bereitet. Es handelt sich hier (angeblich) um eine Möglichkeit, einen String, der die hexadezimale Repräsentation einer Zahl enthält, in einen Integer (hier vom Typ Long) umzuwandeln:

C++:
static const long hextable[] =
{
   [0 ... 255] = -1,                     // bit aligned access into this table is considerably
   ['0'] = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // faster for most modern processors,
   ['A'] = 10, 11, 12, 13, 14, 15,       // for the space conscious, reduce to
   ['a'] = 10, 11, 12, 13, 14, 15        // signed char.
};

/**
 * @brief convert a hexidecimal string to a signed long
 * will not produce or process negative numbers except
 * to signal error.
 *
 * @param hex without decoration, case insensitive.
 *
 * @return -1 on error, or result (max (sizeof(long)*8)-1 bits)
 */
long hexdec(unsigned const char *hex)
{
  long ret = 0;
  while (*hex && ret >= 0)
  {
    ret = (ret << 4) | hextable[*hex++];
  }
  return ret;
}
Im Prinzip ist der Code für mich wertlos, da er keine negativen Werte abbilden kann, aber trotzdem möchte ich gerne wissen, was da vor sich geht.

Etwas konkreter: Ich könnte schon verstehen, was in der while-Schleife passiert (eine bitweise Operation), nur störe ich mich an dem hextable[] Konstrukt, denn sowas habe ich (in meiner zugegeben kurzen Zeit mit C++) bisher noch nicht gesehen. Es sieht zunächst nach einem Array aus, ist dann aber doch keins. Wie nennt man sowas?

Leider hatte ich noch keine Zeit, den Code zu kompilieren und auf einem AVR hochzuladen, aber vielleicht mag mir ja jemand auf die Sprünge helfen und/oder mir sagen, wonach ich auf der allwissenden Müllhalde suchen muss, um mehr zu erfahren.

Vielen Dank,
Vulpecula
 
Dabei seit
Aug. 2010
Beiträge
598
#2
hextable ist ein Array. Die Art wie das deklariert wurde ist mir neu und anscheinend auch nicht Standardkonform. Auf der StackOverflow Seite, die Du verlinkt hast, ist nochmal das volle Array für normale Compiler zu sehen.

Im Prinzip heißt das:
  • Initialisiere Position 0 bis 255 mit -1. Initialisiere Position '0'
  • Initialisiere Position '0' (=48) mit 0 und die darauffolgenden Positionen mit 1,2,3 usw.
  • Initialisiere Position 'A' (=65) mit 10 und die darauffolgenden Positionen mit 11,12,23, usw
  • Dasselbe nochmal mit 'a' (=141)
So macht das auch Sinn. Die while Schleife zeigt mit *hex auf den String. *hex ist am Ende vom String 0 und beendet somit die while schleife. Mit *hex++ wird hex immer eine Position weiter gesetzt. Die zweite Bedingung ret>=0 ist dafür da, dass die Schleife abbricht wenn auf eine -1 in dem LookUp Array zugegriffen wurde.

Als letztes bleibt noch der Inhalt von while:
hextable[*hex++] holt sich Anhand des ASCII Werts die entsprechende Zahl aus dem LookUp Array. Diese Zahl ist maximal 4 Bit groß. Durch den | Operator wird die Zahl dazu addiert.
(ret << 4) schiebt das Ergebnis vom letzten Durchlauf um 4 Bit weiter, so dass die nächste Zahl in den unteren 4 Bit landen kann.

Ziemlich netter und schneller Code.

Im Prinzip ist der Code für mich wertlos, da er keine negativen Werte abbilden kann
Hex Strings bilden nie direkt negative Werte ab. Das sind einfach nur Bits. Das negative Vorzeichen kommt vom Datentyp. 0xFF kann 255 sein oder -1 (bei einer 8 Bit Variablen).
 
Zuletzt bearbeitet:
Dabei seit
Sep. 2015
Beiträge
28
#3
hextable ist ein Array, das speziell initialisiert wird: designated initializers.

Zuerst werden alle Einträge von Indexposition 0 bis 255 auf -1 gesetzt, also hextable[0]=-1.... Die Angabe ['0'] entspricht im Array der Position 48 (=dezimal wert des ASCII Zeichens '0') und die darauf folgenden Indizes werden einsprechend hochgezählt und mit den rechts stehenden Werten belegt: D.h. die Angabe von ['0'] = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 bewirkt hextable[48]=0, hextable[49]=1, ... , hextable[57]=9. vgl. mit einer ASCII Tabelle. Analog steht ['A'] = 10, 11, 12, 13, 14, 15 für hextable[65]=10, ..., hextable[70]=15....
Ergänzung ()

Designated initializers gibt es seit C99 Standard: https://www.ibm.com/support/knowledgecenter/en/ssw_ibm_i_72/rzarg/designators.htm
Ergänzung ()

Bzw. auch hier Infos dazu: https://en.cppreference.com/w/c/language/array_initialization
 
Zuletzt bearbeitet:
Top