Objective-Cを初めて使用しますが、const
とプリプロセスディレクティブ#define
に関していくつか質問があります。
最初に、#define
を使用して定数の型を定義することは不可能であることがわかりました。何故ですか?
第二に、それらの1つを他の1つよりも使用する利点はありますか?
最後に、どの方法がより効率的かつ/またはより安全ですか?
最初に、#defineを使用して定数の型を定義できないことがわかりましたが、それはなぜですか?
なんで?それは真実ではない:
#define MY_INT_CONSTANT ((int) 12345)
第二に、それらの1つを他の1つよりも使用する利点はありますか?
はい。 #define
は、コンパイルが開始される前でも置き換えられるマクロを定義します。 const
は単に変数を変更するだけなので、変更しようとするとコンパイラはエラーにフラグを立てます。 #define
を使用できるコンテキストがありますが、const
を使用することはできません(ただし、最新のclangを使用して見つけるのに苦労しています)。理論的には、const
は実行可能ファイルのスペースを占有し、メモリへの参照を必要としますが、実際にはこれは重要ではなく、コンパイラによって最適化される場合があります。
const
sは、#define
sよりもはるかにコンパイラーおよびデバッガーに適しています。ほとんどの場合、これは、どちらを使用するかを決定するときに考慮する必要がある重要なポイントです。
#define
を使用でき、const
は使用できないコンテキストを考えてみてください。多くの.c
ファイルで使用したい定数があり、#define
を使用する場合は、ヘッダーに固定するだけです。 const
を使用すると、Cファイルに定義が必要です。
// in a C file
const int MY_INT_CONST = 12345;
// in a header
extern const int MY_INT_CONST;
ヘッダーに。 MY_INT_CONST
は、定義されているものを除き、Cファイルの静的またはグローバルスコープ配列のサイズとして使用できません。
ただし、整数定数の場合は、enum
を使用できます。実際、それはAppleがほとんど常に行うことです。これには#define
sとconst
sの両方の利点がすべてありますが、整数定数に対してのみ機能します。
// In a header
enum
{
MY_INT_CONST = 12345,
};
最後に、どの方法がより効率的かつ/またはより安全ですか?
#define
は理論的にはより効率的ですが、私が言ったように、現代のコンパイラはおそらくほとんど違いがないことを保証します。 #define
は、割り当てを試みるのが常にコンパイラエラーであるという点でより安全です
#define FOO 5
// ....
FOO = 6; // Always a syntax error
const
sをだまして割り当てを行うことができますが、コンパイラは警告を発行する場合があります。
const int FOO = 5;
// ...
(int) FOO = 6; // Can make this compile
プラットフォームによっては、定数が読み取り専用セグメントに配置され、C標準に従って公式に定義されていない動作である場合、実行時に割り当てが失敗する可能性があります。
個人的には、整数定数には、他の型の定数には常にenum
sを使用します。そうしない理由がない限り、const
を使用します。
Cコーダーから:
const
は、内容を変更できない単なる変数です。
ただし、#define name value
は、name
のすべてのインスタンスをvalue
に置き換えるプリプロセッサコマンドです。
たとえば、#define defTest 5
を使用すると、コードのdefTest
のすべてのインスタンスは、コンパイル時に5
に置き換えられます。
同じことを意図していない#define命令とconst命令の違いを理解することが重要です。
const
const
は、初期化されると定数になる、要求された型からオブジェクトを生成するために使用されます。これは、プログラムメモリ内のオブジェクトであり、読み取り専用として使用できることを意味します。オブジェクトは、プログラムが起動されるたびに生成されます。
#define
#define
は、コードの可読性と将来の変更を容易にするために使用されます。定義を使用する場合、名前の背後にある値のみをマスクします。したがって、長方形を使用する場合、対応する値で幅と高さを定義できます。次に、コードでは、数字の代わりに名前があるため、読みやすくなります。
後で幅の値を変更することにした場合、ファイル全体で退屈で危険な検索/置換の代わりに、定義で変更するだけで済みます。コンパイル時に、プリプロセッサはすべての定義名をコード内の値に置き換えます。したがって、それらを使用して時間を無駄にすることはありません。
他の人々のコメントに加えて、#define
を使用するエラーは、プリプロセッサがコンパイラの前にそれらを保持するため、デバッグが難しいことで有名です。
プリプロセッサディレクティブは眉をひそめているので、const
を使用することをお勧めします。プリプロセッサディレクティブはコンパイルの前に解決されるため、プリプロセッサで型を指定することはできません。できますが、次のようなものです。
#define DEFINE_INT(name,value) const int name = value;
そして、それを
DEFINE_INT(x,42)
コンパイラからは次のように見えます
const int x = 42;
最初に、#defineを使用して定数の型を定義できないことがわかりました。なぜですか?
あなたは私の最初のスニペットを見ることができます。
第二に、それらの1つを他の1つよりも使用する利点はありますか?
一般に、プリプロセッサディレクティブの代わりにconst
を使用すると、デバッグに役立ちますが、この場合はそれほどではありません(ただし、引き続き機能します)。
最後に、どの方法がより効率的かつ/またはより安全ですか?
両方とも効率的です。マクロは潜在的に実行時に変更できないため、変数は可能ですが、より安全にできると思います。
以前に#defineを使用して、1つのメソッドからさらに多くのメソッドを作成できるようにしました。
// This method takes up to 4 numbers, we don't care what the method does with these numbers.
void doSomeCalculationWithMultipleNumbers:(NSNumber *)num1 Number2:(NSNumber *)num2 Number3:(NSNumber *)num23 Number3:(NSNumber *)num3;
しかし、3つの数値と2つの数値のみを使用するメソッドも必要なので、2つの新しいメソッドを記述する代わりに、#defineを使用して同じメソッドを使用します。
#define doCalculationWithFourNumbers(num1, num2, num3, num4) \
doSomeCalculationWithMultipleNumbers((num1), (num2), (num3), (num4))
#define doCalculationWithThreeNumbers(num1, num2, num3) \
doSomeCalculationWithMultipleNumbers((num1), (num2), (num3), nil)
#define doCalculationWithTwoNumbers(num1, num2) \
doSomeCalculationWithMultipleNumbers((num1), (num2), nil, nil)
これはかなりクールなものだと思います。メソッドに直接進み、不要なスペースにnilを入れることができることを知っていますが、ライブラリを構築している場合は非常に便利です。また、これはどのように
NSLocalizedString(<#key#>, <#comment#>)
NSLocalizedStringFromTable(<#key#>, <#tbl#>, <#comment#>)
NSLocalizedStringFromTableInBundle(<#key#>, <#tbl#>, <#bundle#>, <#comment#>)
完了です。
定数でこれを行うことができるとは思わないが。ただし、定数はコンパイル前に解決されるプリプロセッサディレクティブであるため、#defineで型を指定できないなど、#defineよりも利点があり、#defineでエラーが発生した場合はデバッグが難しくなります定数。どちらにも利点と欠点がありますが、使用することを決めたプログラマーにすべて依存していると思います。 #defineを使用して表示したことを行うライブラリと、型を指定する必要のある定数変数を宣言する定数の両方を使用してライブラリを作成しました。