C言語なら、オレに聞け! <2>

このエントリーをはてなブックマークに追加
510デフォルトの名無しさん
>>508
リトルエンディアンなら 0x78563412 だね。確かに機種依
存な方法だけど、元の質問者がビッグエンディアンと限定し
てるから、これでも良いんじゃない。

ただ、私だったら、Perl の pack, unpack みたいな関数
を実装して使う。似たような処理が出てきたときに使いまわ
せるし、コードの見通しも良くなるからね。

たとえば、こんな感じ。エラーチェックとか甘々だけど、骨
子は分かるよね?

#include <assert.h>
#include <stdio.h>
#include <stdarg.h>

char
ntoc(const int n)
{
    static const char tbl[] = {
        '0', '1', '2', '3', '4', '5', '6', '7',
        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
    };
    assert(0 <= n && n <= 0xf);
    return (tbl[n]);
};

void
unpack(const unsigned char *dat, const char *fmt, ...)
{
    char *cp;
    int *np;
    long *lp;

    int i;
    unsigned int n;
    va_list ap;

    va_start(ap, fmt);
    for (; *fmt != '\0'; ++fmt)
        switch (*fmt) {
        case 'c':
            cp = va_arg(ap, char *);
            for (i = *++fmt - '0'; i > 0; i -= 2) {
                n = *dat++;
                *cp++ = ntoc(n >> 4);
                *cp++ = ntoc(n & 0xf);
            }
            break;
        case 'd':
            np = va_arg(ap, int *);
            *np = 0;
            for (i = 0; i < 2; ++i) {
                *np <<= 8;
                *np |= *dat++;
            }
            break;
        case 'l':
            lp = va_arg(ap, long *);
            *lp = 0;
            for (i = 0; i < 4; ++i) {
                *lp <<= 8;
                *lp |= *dat++;
            }
            break;
        }

    va_end(ap);
}

int
main(void)
{
    char buf[] = { 0x30, 0x31, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc };
    char c[4];
    int i;
    long l;

    unpack(buf, "c4dl", &c[0], &i, &l);
    printf("c = %.4s, i = %X, l = %lX\n", &c[0], i, l);
    return (0);
}
511498:2001/03/30(金) 07:54
じゃ構造体を使う移植性のあるやつを。

#include <limits.h>

struct T {
char c[2];
char i[2];
char l[4];
};

long getint(const char* p, int n)
{
long x = (signed char)p[0];
int i;
for (i = 1; i < n; ++i) {
x = (x << CHAR_BIT) | (unsigned char)p[i];
}
return x;
}

#define intof(x) getint((x), sizeof(x))

int main(void)
{
static const char buf[] = {0x30, 0x31, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};
const struct T* t = (const struct T *)buf;
printf("c = %.*s, i = %X, l = %lX\n", sizeof(t->c), t->c, intof(t->i), intof(t->l));
return 0;
}
512511:2001/03/30(金) 07:58
すまぬ。sizeof(long) > sizeof(int) な処理系でまずかったかも。

--- a.c~ Fri Mar 30 07:52:31 2001
+++ a.c Fri Mar 30 07:56:43 2001
@@ -16,12 +16,13 @@
return x;
}

-#define intof(x) getint((x), sizeof(x))
+#define intof(x) (int)getint((x), sizeof(x))
+#define longof(x) getint((x), sizeof(x))

int main(void)
{
static const char buf[] = {0x30, 0x31, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};
const struct T* t = (const struct T *)buf;
- printf("c = %.*s, i = %X, l = %lX\n", sizeof(t->c), t->c, intof(t->i), intof(t->l));
+ printf("c = %.*s, i = %X, l = %lX\n", sizeof(t->c), t->c, intof(t->i), longof(t->l));
return 0;
}