● fixed X ユーティリティー

FIXEDVAL値の配列

ローカル、またはグローバルで FIXEDVAL値の一次元配列を確保する場合は、大体が次のような形になると思います。
例1.

#define SIZE        数値幅
#define CNT         要素数

    FIXEDVAL        val[CNT][SIZE];
多くの変数を処理しなければならない場合は、都合の良い形です。
このようにして確保した変数は、次のようにインデックスで参照する事ができます。
    int             i;

    for(i = 0;i < CNT;i++) /* 全ての要素をゼロクリア */
        memset(val[i],0,SIZE);
また、領域はメモリ上で連続していますので、メモリクリア等の処理は
    memset(val,0,CNT * SIZE); /* 全ての要素をゼロクリア */
と、まとめて処理する事もできます。



例1 は二次元配列で FIXEDVAL値の一次元配列を確保していますが、次のようにポインタのテーブルを使用する方法もあります。
例2.

    FIXEDVAL        val1[SIZE],val2[SIZE],val3[SIZE],val4[SIZE],val5[SIZE];
    PFIXEDVAL       tbl[CNT];

    tbl[0] = val1; tbl[1] = val2; tbl[2] = val3; tbl[3] = val4; tbl[4] = val5;
メモリのアドレスを格納するテーブルと実体を分けて確保し、後にテーブルへアドレスを格納し、関連付けます。
面倒な方法ではありますが、実体を直接いじらずに位置の移動を行う事ができる利点があります(ポインタテーブルの中身を入れ替えるだけで良い)。




ユーティリティー関数で配列を作成する

例1 の方法はC/C++の機能だけで十分対応可能です。ユーティリティーでは、作成が面倒な例2 についての関数が用意されています。
例3.

#include <stdlib.h>
#include "fixedX.h"
#include "fixutil.h"

/* メモリ確保関数 */
void * __stdcall        user_alloc(size_t size,void *param)
{
    /*
      ここでは malloc を使用していますが、C++の new や
      Windows API のメモリ関数を使用する事もできます。
    */
    return malloc(size);
}

/* メモリ解放関数 */
void __stdcall          user_free(void *pbase,void *param)
{
    /*
      使用しているメモリ確保関数と対になる解放関数を
      使用する必要があります。

      malloc や calloc の場合は free
      new の場合は delete
      GlobalAlloc の場合は GlobalFree

      etc.
    */
    free(pbase);
}

#include <stdio.h>

#define BIT         32
#define SIZE        (BIT/8)

#define CNT         5

void    main(void )
{
    MEMTABLEINFO    mi;
    MEMFUNC         mf;
    FIXEDVAL        work[SIZE];
    PFIXEDVAL       *pptr;
    char            buf[256];
    int             ret,i;

    /* FIXEDVAL型の一次元配列を作成する */

    mi.width = SIZE;            /* 1 要素の数値幅 */
    mi.cnt = CNT;               /* 配列の要素数 */
    mf.pfmemalloc = user_alloc; /* メモリ確保関数のポインタ */

    if ((ret = fixedutil_alloc_memtable(&mi,&mf)) != STATUS_NORMAL){
        printf("エラー:%s\n",fixedutil_errormes(ret));
        return;
    }

    /* 配列に対しての処理を行う */
    for(i = 0;i < CNT;i++)
        fixedutil_setulval32(mi.ppmem[i],SIZE,i + 20);

    /*
      0 : 20
      1 : 21
      2 : 22
      3 : 23
      4 : 24
    */
    pptr = mi.ppmem;
    for(i = 0;i < mi.cnt;i++){
        fixedutil_unsigned_num2str(*pptr++,SIZE,10,buf,work);
        printf("%d : %s\n",i,buf);
    }

    /* 配列の解放 */
    mf.pfmemfree = user_free;   /* メモリ解放関数のポインタ */
    fixedutil_free_memtable(&mi,&mf);
}
一次元配列の確保は、関数fixedutil_alloc_memtable で行います。MEMTABLEINFO構造体の実体に配列要素数と数値幅をセットし、MEMFUNC構造体の実体にはメモリ確保・解放関数のポインタをセットします。
確保した一次元配列は、MEMTABLEINFO構造体のメンバ ppmem から、自由にアクセスする事ができます。

ユーティリティーでは、メモリを確保する処理をコールバックの形で呼び出し側に依頼しています。呼び出し側は例3 のようにメモリ確保のコールバック関数を用意しなければなりませんが、次のような利点があります。


配列を解放する場合は、fixedutil_alloc_memtable と同じ引数で関数fixedutil_free_memtable を呼び出します。引数は同じですが、設定するメンバが若干異なる事には注意してください。