Das Hinzufügen von char als int führt zu einem unerwarteten Ergebnis

Rainfarn

Ich versuche eine Hex-Bin / Bin-Hex-Konvertierung durchzuführen und zu testen, welche Funktion schneller ist, aber beim Hinzufügen von 'a' als Ganzzahl ist ein seltsamer Fehler aufgetreten.

#include <stdio.h>

/* convert bin to hex char [0-9a-f] */
static inline unsigned char ToHex4bits1(unsigned char znak)
//unsigned char ToHex4bits1(unsigned char znak)
    {
    znak &= 0x0F;
    switch(znak)
        {
        case 10: return 'a';
        case 11: return 'b';
        case 12: return 'c';
        case 13: return 'd';
        case 14: return 'e';
        case 15: return 'f';
        default: return znak + 48;  /// 48  0x30    '0'
        }
    }

/* convert bin to hex char [0-9a-f] */    
static inline unsigned char ToHex4bits2(unsigned char znak)
//unsigned char ToHex4bits2(unsigned char znak)
    {
    //unsigned char add = '0';
    int add = '0';  /// [0-9]; add value of '0' (65 0x41    '0')
    znak &=0x0F;
    if(znak > 9)  /// [a-f]; if `znak' <0x0a, 0x0f> /// just one comparison as `znak' cannot be bigger than 15 anyway (znak &=0x0F;)
        {
        add = 0x61;  /// 'a'; // 87 0x61    'a'
        }
    return znak + add;
    }

//-----------//
int main()
    {
    int i;
    //char z;
    int z; 

    printf("\nToHex4bits1(i)\n");
    for(i=0; i<16; i++)
        {
        z = ToHex4bits1(i);
        printf("%d\t%02x\t%c\n", z, z, z);
        }

    printf("\nToHex4bits2(i)\n");
    for(i=0; i<16; i++)
        {
        z = ToHex4bits2(i);
        printf("%d\t%02x\t%c\n", z, z, z);
        }
    return 0;
    }

Wenn ich es $ gcc -o tohex4bits tohex4bits.c; ./tohex4bitsstarte, bekomme ich folgendes Ergebnis:

ToHex4bits1(i)
48  30  0
49  31  1
(...)
57  39  9
97  61  a
98  62  b
(...)
102 66  f
48  30  0
# which is what I expected

ToHex4bits2(i)
48  30  0
49  31  1
(...)
57  39  9
107 6b  k # that's where things get interesting; it's 10 too much ('k'-'a'==10)
108 6c  l
109 6d  m
110 6e  n
111 6f  o
112 70  p

# which is wrong

Was ist eigentlich falsch an der zweiten Funktion? ToHex4bits2()Warum führt das Hinzufügen von 'a' (97 / 0x61) dazu, dass 'k' (107 / 0x6b) oder 'A' => 'K' hinzugefügt wird?

Stoff

Der Grund ist einfach. Wenn znak10 ist, möchten Sie zurückkehren 'a', aber Sie kehren zurück 'a'+10. Also kehre znak+add-10stattdessen zurück.

Aber du machst es dir extrem schwer. Überall magische Konstanten und extrem komplizierter Code für eine einfache Aufgabe. Dies würde tun:

{
znak &= 0x0F;
if(znak > 9) 
    return znak + 'a' - 10;
else
    return znak + '0';
}

Oder dies, wenn Sie kompakter sein möchten. Sie haben offensichtlich keine Angst vor kompliziertem Code:

{
znak &= 0x0F;
return znak > 9 ? znak + 'a' - 10 : znak + '0';
}

Sie haben erwähnt, dass Sie versuchen, diesen Code zu optimieren. Es fällt mir schwer zu sehen, wie Sie so viel dagegen tun können. Es ist wahrscheinlich, dass Sie besser einen größeren Block optimieren sollten, um festzustellen, ob mit Algorithmen oder Ähnlichem etwas nicht stimmt. Aber wir können eine kleine Sache gegen die erste machen, und es ist diese:

#define likely(x)      __builtin_expect(!!(x), 1) 
#define unlikely(x)    __builtin_expect(!!(x), 0) 
static inline unsigned char ToHex4bits1(unsigned char znak)
{
    {
    znak &= 0x0F;
    // Hint the compiler that the first branch is less likely, which
    // improves branch prediction
    if(unlikely(znak > 9)) 
        return znak + 'a' - 10;
    else
        return znak + '0';
    }
}

Lesen Sie hier darüber: https://www.geeksforgeeks.org/branch-prediction-macros-in-gcc/

Aber ich denke, die schnellste Methode ist folgende:

static inline unsigned char ToHex4bits1(unsigned char znak)
{
    const unsigned char ret[] = { '0', '1', '2', '3', '4', '5', '6', '7',
                                  '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
    return ret[znak & 0x0F];
}

Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.

Bei Verstößen wenden Sie sich bitte [email protected] Löschen.

bearbeiten am
0

Lass mich ein paar Worte sagen

0Kommentare
LoginNach der Teilnahme an der Überprüfung

Verwandte Artikel