はじめに
大学の授業でC言語を使う必要があるのですが、配列の境界チェックがないことが非常に辛かったため、マクロを書きました。
プログラミング初心者ですので、何か誤りや改善点等ございましたらご指摘いただけると幸いです。
コード
一次元配列用
//#define NDEBUG#include <assert.h>
/*
使用例:
RANGE_CHECK_1D(a, 5);
a[5];
*/#define RANGE_CHECK_1D(array, i) \
do { \
assert(0 <= (i)); \
assert((i) < (sizeof(array) / sizeof(*array))); \
} while(0)
二次元配列用
//#define NDEBUG#include <assert.h>
/*
使用例:
RANGE_CHECK_2D(a, 3, 4);
a[3][4];
*/#define RANGE_CHECK_2D(array, i, j) \
do { \
assert(0 <= (i)); \
assert((i) < (sizeof(array) / sizeof(*array))); \
assert(0 <= (j)); \
assert((j) < (sizeof(*array) / sizeof(**array))); \
} while(0)
ポインタ用
関数の引数などで配列を渡すとsizeof()によって配列のサイズを調べられなくなるため、ポインタ用も用意しました。最大インデックスは人力入力です。これを使って新しいマクロを定義して使うこともできます。
//#define NDEBUG#include <assert.h>
#define RANGE_CHECK_1D_P(n, i) \
do { \
assert(0 <= (i)); \
assert((i) < (n)); \
} while(0)
使用例
[]
演算子や単項*
演算子などでアクセスする直前に置いて使います。
デバッグ後も削除しない場合#define NDEBUG
と書かないと速度が低下してしまうため注意してください。
#include <stdio.h>
intmain(void){inta[10]={},b[3][5]={},i,j;for(i=0;i<10;i++){RANGE_CHECK_1D(a,i);printf("%d\n",a[i]);}for(i=0;i<3;i++){for(j=0;j<6;j++){RANGE_CHECK_2D(b,i,j);printf("%d\n",b[i][j]);}}}
参考サイト
https://www.jpcert.or.jp/sc-rules/c-pre10-c.html
https://qiita.com/SaitoAtsushi/items/ee17466c464fb7a270d2