必要なのは数値か、サイズ(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));

 

必要なのがサイズなのか、配列数なのか、目的に沿った方を使いましょう。