82

私はObjective-Cを初めて使用しますがconst、前処理ディレクティブに関していくつか質問があり#defineます。

まず、を使用して定数の型を定義することはできないことがわかりました#define。何故ですか?

第二に、それらの1つを別のものよりも使用する利点はありますか?

最後に、どちらの方法がより効率的および/またはより安全ですか?

4

6 に答える 6

107

まず、#defineを使用して定数の型を定義することは不可能であることがわかりましたが、それはなぜですか?

なんで?それは真実ではない:

#define MY_INT_CONSTANT ((int) 12345)

第二に、それらの1つを別のものよりも使用する利点はありますか?

はい。 #defineコンパイルが開始される前でも置き換えられるマクロを定義します。 const変数を変更しようとするとコンパイラがエラーにフラグを立てるように、変数を変更するだけです。#defineを使用できるが使用できないコンテキストがありますconst(最新のclangを使用して1つを見つけるのに苦労していますが)。理論的には、aconstは実行可能ファイルのスペースを占有し、メモリへの参照を必要としますが、実際にはこれは重要ではなく、コンパイラによって最適化される可能性があります。

constsは、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とsの両方のすべての利点がありますがconst、整数定数に対してのみ機能します。

// In a header
enum
{
    MY_INT_CONST = 12345,
};

最後に、どちらの方法がより効率的および/またはより安全ですか?

#define理論的にはより効率的ですが、私が言ったように、最近のコンパイラはおそらくほとんど違いがないことを保証します。 #define割り当てようとすると常にコンパイラエラーになるという点で、より安全です。

#define FOO 5

// ....

FOO = 6;   // Always a syntax error

constsはだまされて割り当てられる可能性がありますが、コンパイラは警告を発行する場合があります。

const int FOO = 5;

// ...

(int) FOO = 6;     // Can make this compile

プラットフォームによっては、定数が読み取り専用セグメントに配置され、C標準に従って公式に定義されていない動作である場合、実行時に割り当てが失敗する可能性があります。

個人的には、整数定数enumの場合、他のタイプの定数の場合は常にsを使用しますconst。特に理由がない限り、使用します。

于 2012-06-22T10:11:02.260 に答える
17

Cコーダーから:

Aconstは、内容を変更できない変数です。

#define name valueただし、は、のすべてのインスタンスをname。に置き換えるプリプロセッサコマンドですvalue

たとえば、の場合、コード内#define defTest 5のすべてのインスタンスは、コンパイル時にdefTestに置き換えられます。5

于 2012-06-22T09:09:43.213 に答える
11

同じことを意図していない#define命令とconst命令の違いを理解することが重要です。

const

const要求されたタイプからオブジェクトを生成するために使用されます。このオブジェクトは、初期化されると一定になります。これは、プログラムメモリ内のオブジェクトであり、読み取り専用として使用できることを意味します。オブジェクトは、プログラムが起動されるたびに生成されます。

#define

#defineコードの可読性と将来の変更を容易にするために使用されます。定義を使用する場合は、名前の背後にある値のみをマスクします。したがって、長方形を操作する場合、対応する値を使用して幅と高さを定義できます。次に、コードでは、数字の代わりに名前が表示されるため、読みやすくなります。

後で幅の値を変更することにした場合は、ファイル全体で退屈で危険な検索/置換を行う代わりに、定義で値を変更するだけで済みます。コンパイル時に、プリプロセッサは定義されたすべての名前をコード内の値に置き換えます。したがって、それらを使用して時間を無駄にすることはありません。

于 2012-06-22T09:25:20.903 に答える
7

他の人々のコメントに加えて、使用中のエラー#defineは、プリプロセッサがコンパイラの前にそれらを取得するため、デバッグが難しいことで有名です。

于 2012-06-22T09:14:40.623 に答える
3

プリプロセッサディレクティブは嫌われているので、を使用することをお勧めしconstます。プリプロセッサディレクティブはコンパイル前に解決されるため、プリプロセッサでタイプを指定することはできません。ええ、できますが、次のようなものです。

#define DEFINE_INT(name,value) const int name = value;

として使用します

DEFINE_INT(x,42) 

これはコンパイラによって次のように表示されます

const int x = 42;

まず、#defineを使用して定数の型を定義することは不可能であることがわかりましたが、それはなぜですか?

できます、私の最初のスニペットを見てください。

第二に、それらの1つを別のものよりも使用する利点はありますか?

一般に、constプリプロセッサディレクティブの代わりに持つことはデバッグに役立ちますが、この場合はそれほどではありません(ただし、それでもそうです)。

最後に、どちらの方法がより効率的および/またはより安全ですか?

どちらも同じくらい効率的です。マクロは実行時に変更できないため、マクロの方が安全である可能性がありますが、変数は変更できます。

于 2012-06-22T09:06:23.610 に答える
1

私は以前に#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を使用して、表示したことを実行するライブラリと、型を指定する必要のある定数変数を宣言する定数の両方を使用してライブラリを作成しました。

于 2012-06-22T10:27:49.093 に答える