必要なのは数値か、サイズ(byte数)か、配列数か。それが問題
基本は定数定義 #define 文
数値が直接掛かれたソースは手抜きと言われます。定数(#define宣言)を用いて共通化するべきです。
例えば、step 1~3の順に処理するモジュールがあるとして、その状態を表す値として、
1~3という数値を用いたとします。後から、step 2と3の間にもう一つstepを増やす必要が生じた場合、
コード上の3を4に書き換えなければならなくなります。
その場所が1つであれば問題視されないかもしれません。
しかし、複数ある場合、書き換え忘れが発生してしまうかもしれません。
また、別の変数に3を代入する処理があった場合、勘違いしてこれも4に書き換えてしまうかもしれません。
この様に、負わなくてよいリスクを自ら(みずから)呼び込むことになるのです。
多少面倒と感じても、何かしらのキーワードにするべきです。
思いついたコードを早く書き進めるたい、しかし、キーワードを決めるのに思考を割き(さき)たくない、
ということもあるでしょう。
こういったときは無理に気の利いたキーワードを時間をかけて考える必要は有りません。
例えば
#define MOD_X_1_ (1)
これで良いのです。
数値で書いてしまうと、後で気の利いたキーワードに置き換えるのは面倒ですが、
適当に書いたキーワードを別のキーワードに置き換えるのは至極簡単なことです。
コードエディタはもちろんテキストエディタにも、検索と一緒に置き換えの機能が備わってると思います。
但し、何でも定数にすれば良いとは限りません。
↓
サイズには sizeof() 関数を使う。ちゃんと理由があります。
サイズが必要な際、sizeof()でも定数でも良い場合は、sizeof()を用いましょう。
#define TABLE_SIZE (100)
#define TABLE_SIZE_B (200)
int i, sum = 0;
unsigned char data[TABLE_SIZE];
//for(i=0; i < TABLE_SIZE; i++)
for(i=0; i < sizeof(data); i++)
{
sum += data[i];
}
定数を用いた場合、data[TABLE_SIZE_B] の様に別の定数に変更したときに困ります。
data[TABLE_SIZE] → data[TABLE_SIZE_B]
i < TABLE_SIZE → i < TABLE_SIZE_B
定数の変更と共に、関連コードを書き換えなければならないので、それを忘れるとバグになります。
配列数は? サイズとの違いを理解しないと使い分けをミスしてしまいます
配列数が必要な際、indexof()でも定数でも良い場合は、indexof()を用いましょう。
(ここに書いた indexof() は一例です。他の呼び方もあります)
#define indexof(a) (sizeof(a)/sizeof(a[0]))
サイズが必要なのか、配列の数が必要なのかによって、sizeof()かindexof()か使い分けないと困ったことになります。
unsigned charやBYTE型の配列について、配列数を用いる場合、sizeof()でも同じ結果が得られますが
indexof()を使うべきです。
int i, sum = 0;
unsigned char data[TABLE_SIZE];
//for(i=0; i < sizeof(data); i++)
for(i=0; i < indexof(data); i++)
{
sum += data[i];
}
sizeofを使った場合、dataの型をint等に変更したとき、sizeofをindexofに置き換えることを忘れたら
動作がおかしくなってしまいます。
一方で、下記の例のようにサイズが必要なところでindexof()を使ってしまうと問題になるので、何でもindexof()を使えば良い、というわけでは有りません。
//memset(data, 0, indexof(data)); ← 誤り
memset(data, 0, sizeof(data));
必要なのがサイズなのか、配列数なのか、目的に沿った方を使いましょう。