Objective-C'de #define vs const


81

Objective-C'de yeniyim constve önişleme yönergesi ile ilgili birkaç sorum var #define.

İlk olarak, kullanarak sabitin türünü tanımlamanın mümkün olmadığını anladım #define. Neden?

İkincisi, birini diğerine göre kullanmanın herhangi bir avantajı var mı?

Son olarak, hangi yol daha verimli ve / veya daha güvenlidir?

Yanıtlar:


107

İlk olarak, #define kullanarak sabitin türünü tanımlamanın mümkün olmadığını anladım, bu neden?

Neden ne? Bu doğru değil:

#define MY_INT_CONSTANT ((int) 12345)

İkincisi, birini diğerine göre kullanmanın herhangi bir avantajı var mı?

Evet. #definederleme başlamadan önce bile değiştirilen bir makro tanımlar. constyalnızca bir değişkeni değiştirir, böylece değiştirmeye çalışırsanız derleyici bir hatayı işaretler. A kullanabileceğiniz #defineancak a kullanamayacağınız bağlamlar vardır const(en son clang'ı kullanarak bir tane bulmakta zorlansam da). Teorik olarak, a constçalıştırılabilir dosyada yer kaplar ve belleğe bir referans gerektirir, ancak pratikte bu önemsizdir ve derleyici tarafından optimize edilebilir.

consts çok daha derleyici ve hata ayıklayıcı dostudur #define. Çoğu durumda, hangisini kullanacağınıza karar verirken göz önünde bulundurmanız gereken en önemli nokta budur.

Sadece kullanabileceğiniz #defineama kullanamayacağınız bir bağlam düşündüm const. Çok sayıda .cdosyada kullanmak istediğiniz bir sabitiniz #definevarsa, bir başlığa yapıştırmanız yeterlidir. A ile bir constC dosyasında bir tanıma sahip olmanız gerekir ve

// in a C file
const int MY_INT_CONST = 12345;

// in a header
extern const int MY_INT_CONST;

bir başlıkta. MY_INT_CONSTiçinde tanımlandığı dosya dışındaki herhangi bir C dosyasında statik veya genel kapsam dizisi boyutu olarak kullanılamaz.

Bununla birlikte, tamsayı sabitleri için bir enum. Aslında Apple'ın neredeyse değişmez yaptığı şey budur. Bu, hem #defines hem de s'nin tüm avantajlarına sahiptir, constancak yalnızca tamsayı sabitleri için çalışır.

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

Son olarak, hangi yol daha verimli ve / veya daha güvenlidir?

#defineTeoride daha etkilidir, ancak söylediğim gibi, modern derleyiciler muhtemelen çok az fark olmasını sağlar. #defineatamaya çalışmak her zaman bir derleyici hatası olduğundan daha güvenlidir

#define FOO 5

// ....

FOO = 6;   // Always a syntax error

constderleyici uyarılar verebilse de, s atanması için kandırılabilir:

const int FOO = 5;

// ...

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

Platforma bağlı olarak, sabit salt okunur bir bölüme yerleştirilirse ve C standardına göre resmi olarak tanımlanmamış davranışsa, atama çalışma zamanında yine başarısız olabilir.

Şahsen, tamsayı sabitleri enumiçin, diğer türlerdeki sabitler için her zaman s kullanırım , constyapmamak için çok iyi bir nedenim yoksa kullanırım.


Eski olduğunu biliyorum, ancak tanımlayabileceğiniz bir sabit kullanamayacağınız bir örnek, "#define MY_NSNUM_CONSTANT @ 5" olup "NSNumber * const MY_NSNUM_CONSTANT = @ 5" kullanılarak yapılamaz
shortstuffsushi

#Define'ın yürütülebilir dosyada const'tan daha fazla yer kapladığını iddia ediyorum. Sabit bir kez depolanır, ancak her kullandığınızda bir #define çarpılır, çünkü yalnızca metin değiştirme işlemidir. Ama fark önemsiz olduğu için gereksiz yere bilgiçlik yapıyorum.
Ryan Ballantyne

@RyanBallantyne Dize sabitleri gibi şeyler için haklı olabileceğini düşünüyorum, ancak tamsayı sabitleri için doğru değilsiniz çünkü sabiti tek bir yerde saklasanız bile, ona erişmek için en az bir kadar büyük adresine ihtiyacınız var int. Bununla birlikte, modern bir derleyicide herhangi bir fark yaratırsa çok şaşırırdım.
JeremyP

16

Bir C kodlayıcıdan:

A const, içeriği değiştirilemeyen bir değişkendir.

#define name valueAncak tüm örneklerini yerini alan bir önişlemci komutu nameile value.

Örneğin, eğer siz #define defTest 5, defTestkodunuzdaki tüm örnekleri 5derlediğinizde ile değiştirilecektir .


11

Aynı şeylere yönelik olmayan #define ve const komutları arasındaki farkı anlamak önemlidir.

const

constbaşlatıldıktan sonra sabit olacak, sorulan türden bir nesne oluşturmak için kullanılır. Program belleğindeki bir nesne olduğu ve salt okunur olarak kullanılabileceği anlamına gelir. Nesne, program her başlatıldığında oluşturulur.

#define

#definekod okunabilirliğini ve gelecekteki değişiklikleri kolaylaştırmak için kullanılır. Bir tanım kullanırken, yalnızca bir adın arkasındaki değeri maskelersiniz. Bu nedenle, bir dikdörtgenle çalışırken, genişlik ve yüksekliği karşılık gelen değerlerle tanımlayabilirsiniz. Daha sonra kodda, sayılar yerine isimler olacağı için okunması daha kolay olacaktır.

Daha sonra genişliğin değerini değiştirmeye karar verirseniz, tüm dosyanızda sıkıcı ve tehlikeli bir bul / değiştir yerine yalnızca tanımda değiştirmeniz gerekir. Derleme sırasında, önişlemci, tanımlanan tüm adı koddaki değerlerle değiştirecektir. Dolayısıyla onları kullanırken zaman kaybetmezsiniz.


7

Diğer kişilerin yorumlarına ek #defineolarak, ön işlemci bunları derleyiciden önce ele geçirdiğinden , kullanım hatalarının ayıklanması oldukça zordur.


3

Ön işlemci yönergeleri hoş karşılanmadığı için, bir const. Ön işlemcili bir tür belirtemezsiniz çünkü bir ön işlemci yönergesi derlemeden önce çözülür. Yapabilirsin, ama şöyle bir şey:

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

ve olarak kullan

DEFINE_INT(x,42) 

derleyici tarafından şu şekilde görülebilir

const int x = 42;

İlk olarak, #define kullanarak sabitin türünü tanımlamanın mümkün olmadığını anladım, bu neden?

İlk parçamı görebilirsin.

İkincisi, birini diğerine göre kullanmanın herhangi bir avantajı var mı?

Genelde constbir ön işlemci yerine bir yönergeye sahip olmak hata ayıklamaya yardımcı olur, bu durumda olduğu kadar değil (yine de yardımcı olur).

Son olarak, hangi yol daha verimli ve / veya daha güvenlidir?

Her ikisi de aynı derecede etkilidir. Makronun çalışma sırasında değiştirilemeyeceği için potansiyel olarak daha güvenli olabileceğini söyleyebilirim , oysa bir değişken olabilir.


const ...Makro kullanmak yerine neden sadece yazın ?
Ed Heal

1
@EdHeal yapma. Ben sadece "#define kullanarak sabitin türünü tanımlamanın mümkün olmadığını anladım, neden bu?"
Luchian Grigore

1
> pre-processor directives are frowned upon[kaynak belirtilmeli]
Ben Leggiero

Sanırım şöyle bir tür kullanabilirsiniz: #define myValue ((double) 2). Anladığım kadarıyla, önişlemci sadece "myValue" 'yu ​​define deyiminde ondan sonra gelen, tip bilgisi dahil olmak üzere değiştirecek.
vomako

1

Daha önce bir yöntemden daha fazla yöntem oluşturmaya yardımcı olmak için #define'ı kullandım, örneğin bir şeyim varmış gibi.

 // 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;

Ama aynı zamanda sadece 3 sayı ve 2 sayı alan bir yönteme ne sahip olmalıyım, bu yüzden iki yeni yöntem yazmak yerine, aynısını #define kullanarak kullanacağım.

 #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)

Bence bu sahip olunması çok güzel bir şey, doğrudan yönteme gidebileceğinizi ve istemediğiniz alanlara sıfır koyabileceğinizi biliyorum, ancak bir kütüphane oluşturuyorsanız çok yararlıdır. Ayrıca bu nasıl

     NSLocalizedString(<#key#>, <#comment#>)
     NSLocalizedStringFromTable(<#key#>, <#tbl#>, <#comment#>)
     NSLocalizedStringFromTableInBundle(<#key#>, <#tbl#>, <#bundle#>, <#comment#>)

yapılır.

Halbuki bunu sabitlerle yapabileceğine inanmıyorum. Ancak, #define ile bir tür belirtemezsiniz, çünkü bu derlemeden önce çözülen bir ön işlemci yönergesidir ve #define ile bir hata alırsanız, hata ayıklamak daha zordur. sabitler. Her ikisinin de yararları ve dezavantajları vardır, ancak hepsinin kullanmaya karar verdiğiniz programcıya bağlı olduğunu söyleyebilirim. Gösterdiğim şeyi yapmak için #define kullanarak her ikisiyle bir kitaplık ve üzerinde bir tür belirtmem gereken sabit değişkenleri bildirmek için sabitler yazdım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.