関数へのポインターの出力(C++ 編)

fptostr.c を、C++ で書き直してみた。
これで、「CHAR_BIT が 4 の倍数の場合にしか対応していない」という制限は無くなった。

fptostr.cpp

#include <bitset>
#include <cstring>
#include <limits>
#include <string>
#include <iostream>

typedef int (*funcptr_t)();

std::string fptostr(funcptr_t p)
{
    static const char *xdigits = "0123456789abcdef";
    const int bom = 1;
    const bool is_little_endian = *reinterpret_cast<const char *>(&bom) == 1;
    const std::size_t u_char_bits = std::numeric_limits<unsigned char>::digits;
    const std::size_t funcptr_t_bits = sizeof(funcptr_t) * u_char_bits;
    const std::size_t funcptr_t_digits = (funcptr_t_bits+3)/4;
    const std::bitset<funcptr_t_bits> mask = 0xf;

    unsigned char cary[sizeof(p)];
    std::memcpy(cary, &p, sizeof(p));
    std::bitset<funcptr_t_bits> bits;
    if ( is_little_endian ) {
        bits = cary[sizeof(p)-1];
        for ( int i = sizeof(p)-2; i >= 0; --i ) {
            bits <<= u_char_bits;
            bits |= cary[i];
        }
    }
    else {
        bits = cary[0];
        for ( int i = 1; i < sizeof(p); ++i ) {
            bits <<= u_char_bits;
            bits |= cary[i];
        }
    }

    std::string str;
    str.reserve(2+funcptr_t_digits);
    str.insert(str.begin(), xdigits[(bits & mask).to_ulong()]);
    for ( int i = 1; i < funcptr_t_digits; ++i ) {
        bits >>= 4;
        str.insert(str.begin(), xdigits[(bits & mask).to_ulong()]);
    }

    return str.insert(0, "0x");
}

int main()
{
    static const funcptr_t fps[] = {
        reinterpret_cast<funcptr_t>(main)
        , reinterpret_cast<funcptr_t>(fptostr)
        , NULL
    };

    for ( int i = 0; fps[i]; ++i ) {
        std::cout
            << "----\n"
            << "(void*) => " << (const void *)fps[i] << "\n"
            << "fptostr => " << fptostr(fps[i]) << "\n";
    }
}

実行例(i386/FreeBSD 6.2/g++ 3.4.6)

----
(void*) => 0x8048d6c
fptostr => 0x08048d6c
----
(void*) => 0x8048ad8
fptostr => 0x08048ad8

実行例(i686/CYGWIN_NT-5.1/g++ 3.4.4)

----
(void*) => 0x4014d6
fptostr => 0x004014d6
----
(void*) => 0x401150
fptostr => 0x00401150

実行例(i686/Windows XP/Visual Studio 2005)

----
(void*) => 00401250
fptostr => 0x00401250
----
(void*) => 00401000
fptostr => 0x00401000