
タイトルの通り、defineで定義した値を配列のサイズ指定に使いたいと考えています。
この場合、次のような使い方をしても問題ないのでしょうか?
/* サンプルここから */
#define SIZE_A 10
#define SIZE_B 20
#define SIZE_ALL (SIZE_A * SIZE_B)
cahr ARR[SIZE_ALL];
/* サンプルここまで */
コンパイル時にワーニング等はありませんが、int型という型を宣言していないSIZE_ALLを要素数として使用するのが不安に感じるのですが問題ないのでしょうか?
int SIZE_int = SIZE_ALL;
とdefineした値を明示的にint型変数に代入した上で、
cahr ARR[SIZE_int];
とすべきなのでしょうか?
初歩的な質問ですが、ご教示お願いします。
No.3ベストアンサー
- 回答日時:
★特に問題ありません。
・普通に define された定数を掛け算などして新しい記号定数を定義します。
そしてその記号定数を配列などの添え字に使います。
そもそも define された定数は通常は int 型と同じになります。
#define SIZE_A 10…int型
#define SIZE_A 10L…long型
#define SIZE_A 10LL…long long型
となります。
『L』や『LL』のサフィックスを付けないとすべて int 型に解釈されます。
つまり、プリプロセッサ命令は単純な文字列の置換ですのでサフィックスを
付けないと int 型になるわけですよ。
・もし char 型にしたいならキャストを指定します。
例えば
#define SIZE_A ((char)(10))
とします。
・もう既に回答がありますが
>int SIZE_int = SIZE_ALL;
>とdefineした値を明示的にint型変数に代入した上で、
>cahr ARR[SIZE_int];
>とすべきなのでしょうか?
↑
この方法は新しい記述方法です。
1999年の最新のC言語の規格です。
この C99 にすべてのコンパイラが対応しているわけではないため使わない方が
良いかもしれません。この記述が利用できれば便利なこともありますが…。
・最後にカッコをつけた方が良いですよ。
#define SIZE_A (10)
#define SIZE_B (20)
#define SIZE_ALL (SIZE_A * SIZE_B)
という風に SIZE_A、SIZE_B に括弧を付けます。
これは今後 SIZE_A を『10 + 20』と定義した際に括弧がないと計算式が
正しくなくなるので付けるように習慣を付けておいた方が良いということです。
つまり今後
#define SIZE_A 10 + 20
#define SIZE_B 20 * 3
#define SIZE_ALL (SIZE_A * SIZE_B)
と定義したとします。
すると SIZE_ALL は (10 + 20 * 20 * 3) と置換されますが計算式が掛け算を先に
する数学上のルールより意図しない結果になります。正しくは SIZE_ALL=1800 に
なるべくところが SIZE_ALL=1210 となってしまいます。
・これを防ぐには2つ。
#define SIZE_A (10 + 20)
#define SIZE_B (20 * 3)
#define SIZE_ALL (SIZE_A * SIZE_B)
もしくは
#define SIZE_A 10 + 20
#define SIZE_B 20 * 3
#define SIZE_ALL ((SIZE_A) * (SIZE_B))
と定義します。
どちらにカッコを付けても同じですが私はすべてにカッコを付ける派です。
・参考にして下さい。
懇切丁寧な説明、ありがとうございます。
参照している書籍がビギナー向けのものばかりのためか、defineに
関する記述が少なく困っているところでした。
大変参考になりました。
No.2
- 回答日時:
#define で定義された文字列は「コンパイルされる前に」プリプロセッサによって単純に置き換えられます。
なので、char ARR[SIZE_ALL]; なる宣言はコンパイラからは char ARR[10*20]; に見えます。
gcc -E などで実際に確認してみましょう。
>int SIZE_int = SIZE_ALL;
>とdefineした値を明示的にint型変数に代入した上で、
>char ARR[SIZE_int];
>とすべきなのでしょうか?
逆に、上記の宣言はコンパイル時に SIZE_int がいくつかコンパイラにはわからないので、
C99 に準拠したコンパイラじゃないと通らないと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
long型の定数の末尾にLを付ける...
-
main.c:7:43: warning: implici...
-
DWORDの実際の型は何でしょうか
-
C++のfor文について
-
変数の型を定義しなかった場合...
-
C++のコンストラクタを宣言する...
-
C言語のコンパイルエラー
-
DLLのLPSTR 項目の戻り値の取得...
-
visualstudio C# テキストボッ...
-
C言語のreturnの使い方
-
識別子が定義されていませんと...
-
コンパイルすると error C1083 ...
-
値を返り値に返すのと参照渡し...
-
ハンドルされていない例外が発...
-
2重定義って??
-
DLLでLIBファイルが作成されない
-
sshdログの意味
-
呼び出し時のパラメータが足りない
-
C++でboolにintの値を代入する...
-
直接アドレス指定のポインタの...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
DWORDの実際の型は何でしょうか
-
visualstudio C# テキストボッ...
-
long型の定数の末尾にLを付ける...
-
main.c:7:43: warning: implici...
-
intとINTの違いは?
-
C++のfor文について
-
2重定義って??
-
void func( void )について
-
変数の型を定義しなかった場合...
-
C言語のコンパイルエラー
-
C++でboolにintの値を代入する...
-
ハンドルされていない例外が発...
-
構造体の要素すべてに対する四...
-
構造体の宣言でエラーが出ます。
-
プログラムの中で別のmainを呼...
-
[C++]メンバ関数の仮引数について
-
0除算を判定したい
-
プログラム、どのように書いて...
-
typedef enumの使い方を教えて...
-
enumについて
おすすめ情報