C言語 |#define マクロ形式関数でテーブルを引く
<例>
回路の端子1, 2の信号をそれぞれ2秒ごとに16点測定したところ以下のようなデータをえた。いずれも周期性のある三角波とする。
この回路のスイッチを入れて x秒経過時の電圧値をそれぞれ得るプログラムを書け。ただし測定データを用いるものとする。
<答>
このような測定データは プログラムでは 配列で定義する。その既知の配列テーブルから index を指定し element を得るような機能を実装する場合、#define を用いるとその一行だけで実装が可能だ。#define の処で関数形式マクロを実装することでコンパクトに実装できる場合もあり、しかも余計な変数を定義しないのでメモリの面でもよろしい。
<ソース(全)>
#include <iostream>
using namespace std;
int main(void){
#define PORT1 0
#define PORT2 1
#define NN 16 //周期あたり点数
#define TT 32 //周期 32sec
/* ### 関数形式マクロで 実装 * ### */
#define getIdx(t) (( ( (t) *NN << 1) / TT + 1) >> 1) //指定indexを返す. (a/b+1) >> 1 は四捨五入処理
#define getVol(port,idx) voltage[port][(unsigned int)(idx) & 0xF] //用いる配列の大きさが 16なので 0b1111 でビットマスク
static const unsigned int voltage[2][NN]=
{
{0,5,10,15,20,25,30,35,40,35,30,25,20,15,10,5},
{0,3,6,9,12,15,18,21,24,21,18,15,12,9,6,3}
};
cout << getVol(PORT1,getIdx(25)); //t=25sec のときの PORT1の電圧
cout << getVol(PORT2,getIdx(318)); //t=318sec のときの PORT2の電圧
}
ところで, 最初の 1周期を超えた範囲の element を得ようとすると, そのままでは配列の範囲外になってしまう。なので、
#define getVol(port,idx) voltage[port][(unsigned int)(idx) & 0xF] //用いる配列の大きさが 16なので 0b1111 でビットマスク
このように ビットマスクを取り, index を指定するのだ。ただしこれを可能にするには, 配列の大きさには, 2^n という制約が付く。