2進数リテラルと2進数ダンプ

C++14では2進数リテラルが規格に加わりました。GCCやClangではCでも使えます。というか、もともとコンパイラの独自拡張機能として実装済みだったものが規格になったみたいです。使い方はこんな感じ。

#include <stdio.h>

int main()
{
    char c = 0b01000001;

    printf("0x%X\n", c);
    printf("%c\n", c);

    return 0;
}
$ ./a.out
0x41
A

んー。これ、なにがうれしいんだろう。あんまり使いどころが思いつきません。それから、printf(3)のフォーマットに2進数が追加されたわけではないので、表示はできません。表示したいときはこんなふうにビットマスクをシフトしながら0と1を出力していけばできます。

#include <stdio.h>

int bin_dump(const void *buf, size_t len)
{
    size_t i;
    const unsigned char *ptr = buf;
    unsigned char bit_mask;

    for (i = 0; i < len; i++)
        for (bit_mask = 0x80; bit_mask; bit_mask = bit_mask >> 1)
            if (putchar(ptr[i] & bit_mask ? '1' : '0') == EOF)
                return -1;

    return 0;
}

int main()
{
    char c = 0x41;
    int i = -1431655766;

    printf("0b");
    bin_dump(&c, sizeof(c));
    printf("\n");

    printf("0b");
    bin_dump(&i, sizeof(i));
    printf("\n");

    return 0;
}

実行するとこんな結果が出力されます。

$ ./a.out 
0b01000001
0b10101010101010101010101010101010

32bitsの2進数表示、長すぎて使う気しないですね。64bitsではどうなるのか興味がある方は試してみてください。マルチバイト型の場合は、読むときにバイトオーダーを気にする必要があります。せっかくなので、2進数ダンプだけでなく16進数ダンプする関数も作りました。

#include <stdio.h>

static int __dump_buf(const void *buf, size_t len,
                      int (*dump_char)(unsigned char),
                      int bytes_per_line)
{
    size_t i;
    const unsigned char *ptr = buf;

    for (i = 0; i < len; i++) {
        if (!(i % bytes_per_line))
            if (printf("0x%04zx: ", i) < 0)
                return -1;

        if (dump_char(ptr[i]) == -1)
            return -1;

        if (putchar((i + 1) % bytes_per_line &&
                    i + 1 < len ? ' ' : '\n') == EOF)
                return -1;
    }

    return 0;
}

int hex_dump_char(unsigned char c)
{
    if (printf("%02x", chr) < 0)
        return -1;

    return 0;
}

int bin_dump_char(unsigned char c)
{
    unsigned char bit_mask;

    for (bit_mask = 0x80; bit_mask; bit_mask = bit_mask >> 1)
        if (putchar(c & bit_mask ? '1' :'0') == EOF)
            return -1;

    return 0;
}

int hex_dump(const void *buf, size_t len)
{
    return __dump_buf(buf, len, hex_dump_char, 16);
}

int bin_dump(const void *buf, size_t len)
{
    return __dump_buf(buf, len, bin_dump_char, 8);
}

int main()
{
    size_t i;
    char buf[32];

    for (i = 0; i < sizeof(buf); i++)
        buf[i] = i;

    if (hex_dump(buf, sizeof(buf)) == -1)
        return 1;

    if (bin_dump(buf, sizeof(buf)) == -1)
        return 1;

    return 0;
}

長さlenのバッファbufに格納されたメモリの16進数ダンプ、2進数ダンプを標準出力に書き込みます。成功すると0、失敗すると-1を返します。なにかのお役に立つならどうぞご自由に。

exturn int hex_dump(const void *buf, size_t len);
exturn int bin_dump(const void *buf, size_t len);

/* LICENSE: BSD 2-Clause */

bit_dump.c

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*