クマは森で用を足しますか?

アウトプットは重要です。

16 進文字列とバイト配列を変換する関数を C 言語で書く

下記エントリで Kotlin でやったやつを、C 言語でもやってみました。やってみましたというか、必要に迫られて手早く書きました。またいつか必要になりそうですので、ここに貼っておこうと思います。

cheerio-the-bear.hatenablog.com

C 言語もここのところずっと遠ざかっていましたので、まだ勘を取り戻すにはもう少し時間がかかりそうです。「あっ!unsigned char とかあったんだ!」みたいな感じになってます。慣れてくると、もっとスマートに書けたりするんでしょうねぇ。

16進数の文字列からバイト配列への変換

unsigned char *util_hex_string_to_byte_array(
    const char *string,
    size_t length
)
{
    unsigned char *array;
    int index;
    unsigned char octet;
    char nibble;

    if ((array = (unsigned char *) malloc(length / 2)) == NULL) {
        return NULL;
    }

    for (index = 0; index < length; index++) {
        nibble = string[index];

        if (('0' <= nibble) && (nibble <= '9')) {
            nibble = nibble - '0';
        } else if (('a' <= nibble) && (nibble <= 'f')) {
            nibble = 0x0A + (nibble - 'a');
        } else if (('A' <= nibble) && (nibble <= 'F')) {
            nibble = 0x0A + (nibble - 'A');
        } else {
            free(array);
            return NULL;
        }

        if ((index % 2) == 0) {
            octet = nibble;
        } else {
            array[index / 2] = (octet << 4) + nibble;
        }
    }

    return array;
}

バイト配列から16進数の文字列への変換

static const char *UTIL_CONVERT_TO_HEX_CHAR = "0123456789ABCDEF";

char *util_byte_array_to_hex_string(
    const unsigned char *array,
    size_t length
)
{
    char *string;
    char *destination;
    int index;
    unsigned char octet;

    if (length == 0) {
        return NULL;
    }

    if ((string = destination = (char *) malloc(length * 2 + 1)) == NULL) {
        return NULL;
    }

    for (index = 0; index < length; index++) {
        octet = array[index];
        *destination++ = UTIL_CONVERT_TO_HEX_CHAR[octet / 0x10];
        *destination++ = UTIL_CONVERT_TO_HEX_CHAR[octet % 0x10];
    }

    *destination = '\0';
    return string;
}

使い方

それぞれ、下記のコード例のように使用します。どちらの関数でも内部で malloc() したヒープメモリを返しますので、使い終わったら使用者側で free() を呼んで解放する必要があります。

    const char *data = "00017F8081FEFF";
    unsigned char *array;
    char *string;

    array = util_hex_string_to_byte_array(data, strlen(data));
    assert(array[0] == 0x00);
    assert(array[1] == 0x01);
    assert(array[2] == 0x7F);
    assert(array[3] == 0x80);
    assert(array[4] == 0x81);
    assert(array[5] == 0xFE);
    assert(array[6] == 0xFF);

    string = util_byte_array_to_hex_string(array, strlen(data) / 2);
    assert(strcmp(data, string) == 0);

    free(array);
    free(string);

github.com