掲示板ランキング  ダブル用  ワイドダブル用  クィーン用  キング用  ポケットコイル  低反発マットレス


掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板1

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧

No.7473

変数群の16進出力
投稿者---chu-(2007/05/23 23:35:10)


テスト環境: Win2000, bcc32 (リトルエンディアン)
実行環境: SH2 shc (ビッグエンディアン)

データを格納している変数群を16進出力しようとしています。
例えば、下記[test.c]の var_char〜arr_st[2] を順に出力すると、下記[期待する出力]のようにします。

16進出力する変数の増加や減少に簡単に対応できるようにしたいと考え、
テーブルへ変数を登録/削除するだけで変更できるようにと、下記[test.c]のように組みました。
実行環境はビッグエンディアンなので、このコードで期待する出力を得られるはずなのですが、
環境に依存したコードはやはり気持ち悪いのでできれば改善したいと考えています。

リトルエンディアンの環境でも下記[期待する出力]を得られるようにしたいのですが、
今のところ解決する方法が思いつきません。
アイデアを頂けないでしょうか。

[test.c]
#include    <stdio.h>

typedef unsigned char   uchar;

#define ARRAYSIZE(array)    (sizeof(array) / sizeof((array)[0]))

#pragma pack(1)
typedef struct {
    char    c;
    short   s;
    long    l;
} st_t;
#pragma pack()

char    var_char =      0x11;
short   var_short =     0x2233;
long    var_long =      0x44556677;
st_t    var_st =        {0x88, 0x99AA, 0xBBCCDDEE};
char    arr_char[2] =   {0xFF, 0x11};
short   arr_short[2] =  {0x2233, 0x4455};
long    arr_long[2] =   {0x66778899, 0xAABBCCDD};
st_t    arr_st[2] =     {{0xEE, 0xFF11, 0x22334455}, {0x66, 0x7788, 0x99AABBCC}};

typedef struct {
    void    *begin;     /* 領域開始アドレス */
    int     size;       /* 領域サイズ       */
} area_t;

const   area_t  table[] = {
    {   &var_char,      sizeof(var_char)    },  /* 0 */
    {   &var_short,     sizeof(var_short)   },  /* 1 */
    {   &var_long,      sizeof(var_long)    },  /* 2 */
    {   &var_st,        sizeof(var_st)      },  /* 3 */
    {   &arr_char[0],   sizeof(arr_char)    },  /* 4 */
    {   &arr_short[0],  sizeof(arr_short)   },  /* 5 */
    {   &arr_long[0],   sizeof(arr_long)    },  /* 6 */
    {   &arr_st[0],     sizeof(arr_st)      },  /* 7 */
};

int main(void)
{
    uchar   *p;
    int     n;
    int     i, j;

    puts("//デバッグ用出力");
    for (i = 0; i < ARRAYSIZE(table); i++) {
        printf("%d: ", i);
        p = table[i].begin;
        n = table[i].size;
        for (j = 0; j < n; j++) {
            printf("%02X ", p[j]);
        }
        printf("\n");
    }

    puts("//実使用出力");
    for (i = 0; i < ARRAYSIZE(table); i++) {
        p = table[i].begin;
        n = table[i].size;
        for (j = 0; j < n; j++) {
            printf("%02X", p[j]);
        }
    }

    return 0;
}

[テスト環境での実行結果]
>bcc32 test.c
Borland C++ 5.5 for Win32 Copyright (c) 1993, 2000 Borland
test.c:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
>test
//デバッグ用出力
0: 11
1: 33 22
2: 77 66 55 44
3: 88 AA 99 EE DD CC BB
4: FF 11
5: 33 22 55 44
6: 99 88 77 66 DD CC BB AA
7: EE 11 FF 55 44 33 22 66 88 77 CC BB AA 99
//実使用出力
1133227766554488AA99EEDDCCBBFF113322554499887766DDCCBBAAEE11FF55443322668877CCBBAA99
>

[期待する出力]
112233445566778899AABBCCDDEEFF112233445566778899AABBCCDDEEFF112233445566778899AABBCC



この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:変数群の16進出力 7474 たかぎ 2007/05/24 00:36:12
<子記事> Re:変数群の16進出力 7475 円零 2007/05/24 12:58:58
<子記事> Re:変数群の16進出力 7476 chu- 2007/05/24 15:33:05
<子記事> Re:変数群の16進出力(浮動小数点数) 7484 chu- 2007/05/25 09:26:12
<子記事> Re:変数群の16進出力 7485 chu- 2007/05/25 13:37:13


No.7474

Re:変数群の16進出力
投稿者---たかぎ(2007/05/24 00:36:12)
http://takagi.in/


いまいちな方法ですが...
typedef struct {
    const void *begin;        /* 領域開始アドレス */
    void (*fn)(const void*);  /* 出力関数 */
} area_t;

void dump_char(const void *p)
{
  printf("%.*X", sizeof(char)*2, *(const char*)p);
}

const   area_t  table[] = {
    {   &var_char,  &dump_char    },  /* 0 */
    ...

というのはどうでしょう?
少なくともバイトオーダーに依存しない実装は可能になります。


この投稿にコメントする

削除パスワード

No.7475

Re:変数群の16進出力
投稿者---円零(2007/05/24 12:58:58)


愚直に識別して処理を切り替えるのではダメでしょうか。
#include <stdio.h>
#include <stdlib.h>

typedef unsigned char uchar;

#define ARRAYSIZE(array) (sizeof(array) / sizeof((array)[0]))

#pragma pack(1)
typedef struct {
    char    c;
    short   s;
    long    l;
} st_t;
#pragma pack()

char    var_char =      0x11;
short   var_short =     0x2233;
long    var_long =      0x44556677;
st_t    var_st =        {0x88, 0x99AA, 0xBBCCDDEE};
char    arr_char[2] =   {0xFF, 0x11};
short   arr_short[2] =  {0x2233, 0x4455};
long    arr_long[2] =   {0x66778899, 0xAABBCCDD};
st_t    arr_st[2] =     {{0xEE, 0xFF11, 0x22334455}, {0x66, 0x7788, 0x99AABBCC}};

typedef struct {
    void    *begin;     /* 領域開始アドレス */
    int     size;       /* 領域サイズ       */
} area_t;

const   area_t  table[] = {
    {   &var_char,      sizeof(var_char)    },  /* 0 */
    {   &var_short,     sizeof(var_short)   },  /* 1 */
    {   &var_long,      sizeof(var_long)    },  /* 2 */
    {   &var_st,        sizeof(var_st)      },  /* 3 */
    {   &arr_char[0],   sizeof(arr_char)    },  /* 4 */
    {   &arr_short[0],  sizeof(arr_short)   },  /* 5 */
    {   &arr_long[0],   sizeof(arr_long)    },  /* 6 */
    {   &arr_st[0],     sizeof(arr_st)      },  /* 7 */
};

int main(void)
{
    uchar   *p, *q;
    int     n, m;
    int     i, j;
    int     isbigendian, step;

    if(sizeof(int) == 1) exit(EXIT_FAILURE);
    m = 1;
    q = (uchar *)&m;
    while(*q != 1) q++;
    if((uchar *)&m == q) isbigendian = 0;                       //リトルエンディアン
    else if((uchar *)&m == q + sizeof(int) - 1) isbigendian = 1;//ビッグエンディアン
    else exit(EXIT_FAILURE);

    puts("//デバッグ用出力");
    for (i = 0; i < ARRAYSIZE(table); i++) {
        printf("%d: ", i);
        p = table[i].begin;
        n = table[i].size;
        step = isbigendian * 2 - 1;
        for (j = isbigendian? 0: n - 1; isbigendian? j < n: j >= 0; j += step) {
            printf("%02X ", p[j]);
        }
        printf("\n");
    }

    puts("//実使用出力");
    for (i = 0; i < ARRAYSIZE(table); i++) {
        p = table[i].begin;
        n = table[i].size;
        step = isbigendian * 2 - 1;
        for (j = isbigendian? 0: n - 1; isbigendian? j < n: j >= 0; j += step) {
            printf("%02X", p[j]);
        }
    }
    return 0;
}




この投稿にコメントする

削除パスワード

No.7476

Re:変数群の16進出力
投稿者---chu-(2007/05/24 15:33:05)


返信ありがとうございます。


>たかぎさん
下記[test2.c]のように実装し、期待する出力を得ることができました。

頂いた案や前回のソースから以下を変更しているので理由を示します。

・入力にも使いたいので、const void *begin; の const を外しました。
・printf("%.*X", sizeof(char)*2, *(const char*)p); は、0x80以上の値が符号拡張されて具合が悪かったですし、
  sizeofを使っても"X"と"lX"の違いは吸収できないので、単純な記述に変更しました。
・配列変数の扱いが変わったので、beginの変数名とコメントを ptrと/* 変数へのポインタ */ へ変更しました。

[test2.c]
#include    <stdio.h>

typedef unsigned char   uchar;
typedef unsigned short  ushort;

#define ARRAYSIZE(array)    (sizeof(array) / sizeof((array)[0]))

#pragma pack(1)
typedef struct {
    char    c;
    short   s;
    long    l;
} st_t;
#pragma pack()

char    var_char =      0x11;
short   var_short =     0x2233;
long    var_long =      0x44556677;
st_t    var_st =        {0x88, 0x99AA, 0xBBCCDDEE};
char    arr_char[2] =   {0xFF, 0x11};
short   arr_short[2] =  {0x2233, 0x4455};
long    arr_long[2] =   {0x66778899, 0xAABBCCDD};
st_t    arr_st[2] =     {{0xEE, 0xFF11, 0x22334455}, {0x66, 0x7788, 0x99AABBCC}};

int put_char(const void *ptr, char *buf)
{
    const   char    *p = ptr;
    int n;

    n = sprintf(buf, "%02X", (uchar)*p);
    return (n > 0) ? n : 0;
}

int put_short(const void *ptr, char *buf)
{
    const   short   *p = ptr;
    int n;

    n = sprintf(buf, "%04X", (ushort)*p);
    return (n > 0) ? n : 0;
}

int put_long(const void *ptr, char *buf)
{
    const   long    *p = ptr;
    int n;

    n = sprintf(buf, "%08lX", *p);
    return (n > 0) ? n : 0;
}

int put_st_t(const void *ptr, char *buf)
{
    const   st_t    *p = ptr;
    int n;

    n = sprintf(buf, "%02X%04X%08lX",
                     (uchar)p->c, (ushort)p->s, p->l);
    return (n > 0) ? n : 0;
}

int put_char2(const void *ptr, char *buf)
{
    const   char    (*p)[2] = ptr;
    int n;

    n = sprintf(buf, "%02X"
                     "%02X",
                     (uchar)(*p)[0],
                     (uchar)(*p)[1]);
    return (n > 0) ? n : 0;
}

int put_short2(const void *ptr, char *buf)
{
    const   short   (*p)[2] = ptr;
    int n;

    n = sprintf(buf, "%04X"
                     "%04X",
                     (ushort)(*p)[0],
                     (ushort)(*p)[1]);
    return (n > 0) ? n : 0;
}

int put_long2(const void *ptr, char *buf)
{
    const   long    (*p)[2] = ptr;
    int n;

    n = sprintf(buf, "%08lX"
                     "%08lX",
                     (*p)[0],
                     (*p)[1]);
    return (n > 0) ? n : 0;
}

int put_st_t2(const void *ptr, char *buf)
{
    const   st_t    (*p)[2] = ptr;
    int n;

    n = sprintf(buf, "%02X%04X%08lX"
                     "%02X%04X%08lX",
                     (uchar)(*p)[0].c, (ushort)(*p)[0].s, (*p)[0].l,
                     (uchar)(*p)[1].c, (ushort)(*p)[1].s, (*p)[1].l);
    return (n > 0) ? n : 0;
}

typedef struct {
    void    *ptr;                               /* 変数へのポインタ */
    int     (*put)(const void *ptr, char *buf); /* 16進出力関数     */
/*  int     (*get)(void *ptr, const char *buf); /* 16進入力関数     */
} area_t;

const   area_t  table[] = {
    {   &var_char,  put_char,   /*get_char,*/   },  /* 0 */
    {   &var_short, put_short,  /*get_short,*/  },  /* 1 */
    {   &var_long,  put_long,   /*get_long,*/   },  /* 2 */
    {   &var_st,    put_st_t,   /*get_st_t,*/   },  /* 3 */
    {   &arr_char,  put_char2,  /*get_char2,*/  },  /* 4 */
    {   &arr_short, put_short2, /*get_short2,*/ },  /* 5 */
    {   &arr_long,  put_long2,  /*get_long2,*/  },  /* 6 */
    {   &arr_st,    put_st_t2,  /*get_st_t2,*/  },  /* 7 */
};

int main(void)
{
    char    buf[256];
    char    *p;
    int     n;
    int     i;

    p = buf;
    for (i = 0; i < ARRAYSIZE(table); i++) {
        n = table[i].put(table[i].ptr, p);
        p += n;
    }
    puts(buf);

    return 0;
}

[test2.cの実行結果]
112233445566778899AABBCCDDEEFF112233445566778899AABBCCDDEEFF112233445566778899AABBCC


>円零さん
残念ながら、領域内の走査方向を逆にしただけでは下記[逆走査実行結果]のとおり、
構造体や配列に対応できません。

[逆走査実行結果]
//デバッグ用出力
0: 11
1: 22 33
2: 44 55 66 77
3: BB CC DD EE 99 AA 88                         ← 正しくない
4: 11 FF                                        ← 正しくない
5: 44 55 22 33                                  ← 正しくない
6: AA BB CC DD 66 77 88 99                      ← 正しくない
7: 99 AA BB CC 77 88 66 22 33 44 55 FF 11 EE    ← 正しくない
//実使用出力
11223344556677BBCCDDEE99AA8811FF44552233AABBCCDD6677889999AABBCC77886622334455FF11EE

[期待する出力]
112233445566778899AABBCCDDEEFF112233445566778899AABBCCDDEEFF112233445566778899AABBCC



この投稿にコメントする

削除パスワード

No.7477

Re:変数群の16進出力
投稿者---Hermit(2007/05/24 20:59:54)


配列に関しては、構造体中に繰り返し情報を入れておけば、
わざわざ配列用に関数を作る必要はない気がしますが。
2 を超える物があればの話ですけど。


この投稿にコメントする

削除パスワード

No.7478

Re:変数群の16進出力
投稿者---かずま(2007/05/24 21:03:26)


> 配列に関しては、構造体中に繰り返し情報を入れておけば、
> わざわざ配列用に関数を作る必要はない気がしますが。
> 2 を超える物があればの話ですけど。

私もそう思ったので、短くしてみました。
#include <stdio.h>

typedef unsigned char   uchar;
typedef unsigned short  ushort;
typedef unsigned long   ulong;

#define ARRAYSIZE(array)    (sizeof(array) / sizeof((array)[0]))

typedef struct {
    char    c;
    short   s;
    long    l;
} st_t;

char  var_char =     0x11;
short var_short =    0x2233;
long  var_long =     0x44556677;
st_t  var_st =       {0x88, 0x99AA, 0xBBCCDDEE};
char  arr_char[2] =  {0xFF, 0x11};
short arr_short[2] = {0x2233, 0x4455};
long  arr_long[2] =  {0x66778899, 0xAABBCCDD};
st_t  arr_st[2] =    {{0xEE, 0xFF11, 0x22334455}, {0x66, 0x7788, 0x99AABBCC}};

typedef struct area_t {
    void *ptr;           /* 変数へのポインタ */
    int   size;          /* 変数のサイズ(1, 2, 4) */
    int   num;           /* 変数の個数 */
    int  (*put)(const struct area_t *ptr, char *buf); /* 16進出力関数 */
} area_t;

int put_data(const area_t *ap, char *buf)
{
    int i, size = ap->size; char *bp = buf; uchar *p = (uchar *)ap->ptr;
    
    for (i = ap->num; i > 0; --i, p += size)
        switch (size) {
        case 1: bp += sprintf(bp, "%02X",  *(uchar *)p); break;
        case 2: bp += sprintf(bp, "%04X", *(ushort *)p); break;
        case 4: bp += sprintf(bp, "%08lX", *(ulong *)p); break;
        }
    return bp - buf;
}

int put_st_t(const area_t *ap, char *buf)
{
    int i;  char *bp = buf;  st_t *p = (st_t *)ap->ptr;

    for (i = ap->num; i > 0; --i, p++)
        bp += sprintf(bp, "%02X%04X%08lX", (uchar)p->c, (ushort)p->s, p->l);
    return bp - buf;
}

const area_t table[] = {
    { &var_char,  1, 1, put_data },  /* 0 */
    { &var_short, 2, 1, put_data },  /* 1 */
    { &var_long,  4, 1, put_data },  /* 2 */
    { &var_st,    0, 1, put_st_t },  /* 3 */
    { arr_char,   1, 2, put_data },  /* 4 */
    { arr_short,  2, 2, put_data },  /* 5 */
    { arr_long,   4, 2, put_data },  /* 6 */
    { arr_st,     0, 2, put_st_t },  /* 7 */
};

int main(void)
{
    char buf[256], *p = buf;  int i;

    for (i = 0; i < ARRAYSIZE(table); i++)
        p += table[i].put(table + i, p);
    puts(buf);
    return 0;
}



この投稿にコメントする

削除パスワード

No.7482

Re:変数群の16進出力
投稿者---chu-(2007/05/25 03:05:04)


返信ありがとうございます。

>Hermitさん
なるほど、言われて気づきました。
要素数を持たせれば何次元配列だろうと共通の出力関数で出力できることを
かずまさんのコードを改造して試し、確認しました。

>かずまさん
参考にさせていただきます。

一つ気になることがあるのでよろしければお教えください。
forループをダウンカウンタで組んでいるのにはなにか理由があるのでしょうか。
あまりダウンカウンタを見かけることがないのでふと気になりました。
私が思いつく理由は、CPUはゼロとの比較が得意であることが多い、くらいです。



この投稿にコメントする

削除パスワード

No.7484

Re:変数群の16進出力(浮動小数点数)
投稿者---chu-(2007/05/25 09:26:12)


浮動小数点数の勉強の為、float, double, long double の変数も
16進出力できるようにしようとしています。

今までの投稿で各型の変数を以下のように16進出力してきました。

・char型    printf("%02X", (uchar)var_char);
・short型   printf("%04X", (ushort)var_short);
・long型    printf("%08lX", var_long);
・構造体型  基本型の出力関数を組み合わせて専用の出力関数を作成

浮動小数点数型変数の16進出力はどのような方法があるでしょうか。
今のところ思いつく方法は以下で、[test3.c]を添付します。

・sizeof(float)==sizeof(long)であればfloatをlongに偽装してlong型用出力関数で出力する。
・円零さんに頂いた回答の方法等でエンディアンを調べて走査方向を決定し、char型用出力関数で順に出力する。

[test3.c]
#include    <stdio.h>
#include    <string.h>

typedef unsigned char   uchar;
typedef long double     ldouble;

int main(void)
{
    float   var_float;
    double  var_double;
    ldouble var_ldouble;
    uchar   *p;
    int     i;

    /*-- データ設定 --*/
    /* 0x12345678を設定 */
    *(long *)&var_float = 0x12345678;

    /* 0x1122334455667788を設定 */
    /* 0_00100010010_(1)0010001100110100010001010101011001100111011110001000
     * + 274-1023=-749 5122918164363144*2y(-52)=1.1375163398692809124668201548047
     * +1.1375163398692809124668201548047*2y(-749)=3.8414120244717306592306445023349e-226
     */
    var_double = 3.8414120244717306e-226;

    /* 0x66778899AABBCCDDEEFFを設定 */
/*  memcpy(&var_ldouble, "\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF", sizeof(var_ldouble));  /* ビッグエンディアン用 */
    memcpy(&var_ldouble, "\xFF\xEE\xDD\xCC\xBB\xAA\x99\x88\x77\x66", sizeof(var_ldouble));  /* リトルエンディアン用 */

    /*-- データ出力 --*/
    printf("0x%08lX\n", *(long *)&var_float);       /* 同サイズのlongを偽装 */

    printf("0x");
    p = (uchar *)&var_double;
/*  for (i = 0; i < sizeof(var_double); i++) {      /* ビッグエンディアン用 */
    for (i = sizeof(var_double)-1; i >= 0; i--) {   /* リトルエンディアン用 */
        printf("%02X", p[i]);
    }
    puts("");

    printf("0x");
    p = (uchar *)&var_ldouble;
/*  for (i = 0; i < sizeof(var_double); i++) {      /* ビッグエンディアン用 */
    for (i = sizeof(var_ldouble)-1; i >= 0; i--) {  /* リトルエンディアン用 */
        printf("%02X", p[i]);
    }
    puts("");

    return 0;
}

[実行結果]
>bcc32 test3.c
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
test3.c:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland

>test3
0x12345678
0x1122334455667788
0x66778899AABBCCDDEEFF

>



この投稿にコメントする

削除パスワード

No.7485

Re:変数群の16進出力
投稿者---chu-(2007/05/25 13:37:13)


ビッグエンディアンとリトルエンディアンで処理を分けてもコード量も可読性もたいして悪化しないことがわかったので、
エンディアンごとに処理を分ける方法をとることにしました。

"%04X"や"%08lX"は使わずすべてバイトごとの出力なので、double等の浮動小数点数型にも対応できました。

[test.c]
#include    <stdio.h>

typedef unsigned char   uchar;
typedef unsigned short  ushort;
typedef unsigned long   ulong;

#define ARRAYSIZE(array)    (sizeof(array) / sizeof((array)[0]))

#pragma pack(1)
typedef struct {
    char    c;
    short   s;
    long    l;
} st_t;
#pragma pack()

char    var_char =          0x11;
short   var_short =         0x2233;
long    var_long =          0x44556677;
st_t    var_st =            {0x88, 0x99AA, 0xBBCCDDEE};
char    arr_char[2] =       {0xFF, 0x11};
short   arr_short[2] =      {0x2233, 0x4455};
long    arr_long[2] =       {0x66778899, 0xAABBCCDD};
st_t    arr_st[2] =         {{0xEE, 0xFF11, 0x22334455}, {0x66, 0x7788, 0x99AABBCC}};
char    arr2_char[3][2] =   {{0xDD, 0xEE}, {0xFF, 0x11}, {0x22, 0x33}};
short   arr2_short[3][2] =  {{0x4455, 0x6677}, {0x8899, 0xAABB}, {0xCCDD, 0xEEFF}};
long    arr2_long[3][2] =   {{0x11223344, 0x55667788}, {0x99AABBCC, 0xDDEEFF11}, {0x22334455, 0x66778899}};
st_t    arr2_st[3][2] =     {{{0xAA, 0xBBCC, 0xDDEEFF11}, {0x22, 0x3344, 0x55667788}},
                             {{0x99, 0xAABB, 0xCCDDEEFF}, {0x11, 0x2233, 0x44556677}},
                             {{0x88, 0x99AA, 0xBBCCDDEE}, {0xFF, 0x1122, 0x33445566}}};
float   var_float =         5.5411644e+33;                  /* 0x778899AA           */
double  var_double =        -1.22256195700545978e-20;       /* 0xBBCCDDEEFF112233   */

typedef struct area_tag {
    void    *begin;                                         /* 開始アドレス */
    int     size;                                           /* 要素サイズ   */
    int     num;                                            /* 要素数       */
    int     (*put)(const struct area_tag *area, char *buf); /* 16進出力関数 */
} area_t;

int put_bytes(const void *src, int size, char *buf)
{
    static  const   int endian_test = 1;
    const   uchar   *it;
    const   uchar   *end;
    char    *p;

    p = buf;
    if (*(char *)&endian_test) {
        /* リトルエンディアン */
        for (end = src, it = end + size - 1; it >= end; it--) {
            p += sprintf(p, "%02X", *it);
        }
    }
    else {
        /* ビッグエンディアン */
        for (it = src, end = it + size; it < end; it++) {
            p += sprintf(p, "%02X", *it);
        }
    }
    return (p - buf == size * 2) ? p - buf : 0;
}

int put_simple_t(const area_t *area, char *buf)
{
    const   uchar   *it;
    const   uchar   *end;
    int     entire_size = area->size * area->num;
    char    *p;

    p = buf;
    for (it = area->begin, end = it + entire_size; it < end; it += area->size) {
        p += put_bytes(it, area->size, p);
    }
    return (p - buf == entire_size * 2) ? p - buf : 0;
}

int put_st_t(const area_t *area, char *buf)
{
    const   st_t    *it;
    const   st_t    *end;
    int     entire_size = area->size * area->num;
    char    *p;

    p = buf;
    for (it = area->begin, end = it + area->num; it < end; it++) {
        p += put_bytes(&it->c, sizeof(it->c), p);
        p += put_bytes(&it->s, sizeof(it->s), p);
        p += put_bytes(&it->l, sizeof(it->l), p);
    }
    return (p - buf == entire_size * 2) ? p - buf : 0;
}

const   area_t  table[] = {
    {   &var_char,          sizeof(var_char),           1,                                              put_simple_t,   },  /* 0  */
    {   &var_short,         sizeof(var_short),          1,                                              put_simple_t,   },  /* 1  */
    {   &var_long,          sizeof(var_long),           1,                                              put_simple_t,   },  /* 2  */
    {   &var_st,            sizeof(var_st),             1,                                              put_st_t,       },  /* 3  */
    {   &arr_char[0],       sizeof(arr_char[0]),        sizeof(arr_char)/sizeof(arr_char[0]),           put_simple_t,   },  /* 4  */
    {   &arr_short[0],      sizeof(arr_short[0]),       sizeof(arr_short)/sizeof(arr_short[0]),         put_simple_t,   },  /* 5  */
    {   &arr_long[0],       sizeof(arr_long[0]),        sizeof(arr_long)/sizeof(arr_long[0]),           put_simple_t,   },  /* 6  */
    {   &arr_st[0],         sizeof(arr_st[0]),          sizeof(arr_st)/sizeof(arr_st[0]),               put_st_t,       },  /* 7  */
    {   &arr2_char[0][0],   sizeof(arr2_char[0][0]),    sizeof(arr2_char)/sizeof(arr2_char[0][0]),      put_simple_t,   },  /* 8  */
    {   &arr2_short[0][0],  sizeof(arr2_short[0][0]),   sizeof(arr2_short)/sizeof(arr2_short[0][0]),    put_simple_t,   },  /* 9  */
    {   &arr2_long[0][0],   sizeof(arr2_long[0][0]),    sizeof(arr2_long)/sizeof(arr2_long[0][0]),      put_simple_t,   },  /* 10 */
    {   &arr2_st[0][0],     sizeof(arr2_st[0][0]),      sizeof(arr2_st)/sizeof(arr2_st[0][0]),          put_st_t,       },  /* 11 */
    {   &var_float,         sizeof(var_float),          1,                                              put_simple_t,   },  /* 12 */
    {   &var_double,        sizeof(var_double),         1,                                              put_simple_t,   },  /* 13 */
};

int main(void)
{
    char    buf[512];
    char    *p;
    int     n;
    int     i;

    p = buf;
    for (i = 0; i < ARRAYSIZE(table); i++) {
        n = table[i].put(&table[i], p);
        if (n == 0) return 1;
        printf("[%2d] %s\n", i, p); /* デバッグ用 */
        p += n;
    }
    puts("---");
    puts(buf);

    return 0;
}



この投稿にコメントする

削除パスワード

No.7486

Re:変数群の16進出力
投稿者---chu-(2007/05/25 13:37:52)


[実行結果]
>bcc32 test.c
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
test.c:
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland

>test
[ 0] 11
[ 1] 2233
[ 2] 44556677
[ 3] 8899AABBCCDDEE
[ 4] FF11
[ 5] 22334455
[ 6] 66778899AABBCCDD
[ 7] EEFF112233445566778899AABBCC
[ 8] DDEEFF112233
[ 9] 445566778899AABBCCDDEEFF
[10] 112233445566778899AABBCCDDEEFF112233445566778899
[11] AABBCCDDEEFF112233445566778899AABBCCDDEEFF112233445566778899AABBCCDDEEFF112233445566
[12] 778899AA
[13] BBCCDDEEFF112233
---
112233445566778899AABBCCDDEEFF112233445566778899AABBCCDDEEFF112233445566778899AABBCCDDEEFF1122334455
66778899AABBCCDDEEFF112233445566778899AABBCCDDEEFF112233445566778899AABBCCDDEEFF112233445566778899AA
BBCCDDEEFF112233445566778899AABBCCDDEEFF112233445566778899AABBCCDDEEFF112233

>



この投稿にコメントする

削除パスワード

No.7487

Re:変数群の16進出力
投稿者---chu-(2007/05/25 16:07:18)


sprintfがEOFを返す可能性を考えなくて済むように、put_bytes()からsprintfを無くしました。
不一致の可能性が無くなったので、put_bytes()/put_simple_t()put_st_t()のreturn部から条件演算子を削除しました。

満足のいくコードを得ることができました。
皆さんありがとうございました。


int put_bytes(const void *src, int size, char *buf)
{
    static  const   int     endian_test = 1;
    static  const   char    hex[16] = "0123456789ABCDEF";
    const   uchar   *it;
    const   uchar   *end;
    char    *p;

    p = buf;
    if (*(char *)&endian_test) {
        /* リトルエンディアン */
        for (end = src, it = end + size - 1; it >= end; it--) {
            *p++ = hex[*it >> 4 & 0xF];
            *p++ = hex[*it & 0xF];
        }
    }
    else {
        /* ビッグエンディアン */
        for (it = src, end = it + size; it < end; it++) {
            *p++ = hex[*it >> 4 & 0xF];
            *p++ = hex[*it & 0xF];
        }
    }
    *p = '\0';
    return size * 2;
}



この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧





掲示板提供:(有)リアル・インテグリティ