私はObjective-Cconst
を初めて使用しますが、前処理ディレクティブに関していくつか質問があり#define
ます。
まず、を使用して定数の型を定義することはできないことがわかりました#define
。何故ですか?
第二に、それらの1つを別のものよりも使用する利点はありますか?
最後に、どちらの方法がより効率的および/またはより安全ですか?
私はObjective-Cconst
を初めて使用しますが、前処理ディレクティブに関していくつか質問があり#define
ます。
まず、を使用して定数の型を定義することはできないことがわかりました#define
。何故ですか?
第二に、それらの1つを別のものよりも使用する利点はありますか?
最後に、どちらの方法がより効率的および/またはより安全ですか?
回答:
まず、#defineを使用して定数の型を定義することは不可能であることがわかりました。それはなぜですか?
なんで?それは真実ではない:
#define MY_INT_CONSTANT ((int) 12345)
第二に、それらの1つを別のものよりも使用する利点はありますか?
はい。 #define
コンパイルが開始される前でも置き換えられるマクロを定義します。 const
変数を変更しようとするとコンパイラがエラーにフラグを立てるように、変数を変更するだけです。を使用できるが使用#define
できないコンテキストがありますconst
(最新のclangを使用して1つを見つけるのに苦労していますが)。理論的には、const
は実行可能ファイル内のスペースを占有し、メモリへの参照を必要としますが、実際にはこれは重要ではなく、コンパイラによって最適化される可能性があります。
const
sは、sよりもはるかにコンパイラとデバッガに適しています#define
。ほとんどの場合、これは、どちらを使用するかを決定するときに考慮する必要がある最も重要なポイントです。
使用できるが使用でき#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
ないという非常に正当な理由がない限り、使用します。
int
です。しかし、それが現代のコンパイラーでまったく違いを生んだとしたら、私は非常に驚きます。
Cコーダーから:
Aconst
は、内容を変更できない単なる変数です。
#define name value
ただし、は、のすべてのインスタンスname
をvalue
。に置き換えるプリプロセッサコマンドです。
たとえば、の場合、コード内の#define defTest 5
すべてのインスタンスはコンパイル時にdefTest
に置き換えられ5
ます。
同じことを意図していない#define命令とconst命令の違いを理解することが重要です。
const
const
は、初期化されると一定になる、要求されたタイプからオブジェクトを生成するために使用されます。これは、プログラムメモリ内のオブジェクトであり、読み取り専用として使用できることを意味します。オブジェクトは、プログラムが起動されるたびに生成されます。
#define
#define
コードの可読性と将来の変更を容易にするために使用されます。定義を使用する場合は、名前の背後にある値のみをマスクします。したがって、長方形を操作する場合、対応する値を使用して幅と高さを定義できます。次に、コードでは、数字の代わりに名前があるため、読みやすくなります。
後で幅の値を変更することにした場合は、ファイル全体で退屈で危険な検索/置換を行う代わりに、定義で値を変更するだけで済みます。コンパイル時に、プリプロセッサは定義されたすべての名前をコード内の値に置き換えます。したがって、それらを使用して時間を無駄にすることはありません。
プリプロセッサディレクティブは嫌われているので、を使用することをお勧めしますconst
。プリプロセッサディレクティブはコンパイル前に解決されるため、プリプロセッサでタイプを指定することはできません。まあ、できますが、次のようなものです。
#define DEFINE_INT(name,value) const int name = value;
として使用します
DEFINE_INT(x,42)
これはコンパイラによって次のように表示されます
const int x = 42;
まず、#defineを使用して定数の型を定義することは不可能であることがわかりました。それはなぜですか?
できます、私の最初のスニペットを見てください。
第二に、それらの1つを別のものよりも使用する利点はありますか?
一般に、const
プリプロセッサディレクティブの代わりに持つことはデバッグに役立ちますが、この場合はそれほどではありません(ただし、それでもそうです)。
最後に、どちらの方法がより効率的および/またはより安全ですか?
どちらも同じくらい効率的です。マクロは実行時に変更できないため、より安全になる可能性がありますが、変数は変更できます。
const ...
マクロを使用する代わりに、単に入力するのはなぜですか?
pre-processor directives are frowned upon
[要出典]
私は以前に#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を使用して表示したことを実行するライブラリと、型を指定する必要のある定数変数を宣言する定数の両方を使用してライブラリを作成しました。