C kitaplığı neden aynı ada sahip makrolar ve işlevler kullanıyor?


20

Gerçekten ilginç olan PJ Plauger'in 'Standart C Kütüphanesi'ni okuyorum. Kitap sadece kütüphanenin nasıl kullanılacağını değil aynı zamanda nasıl uygulandığını da açıklıyor.

ctype.hBölümü okumayı bitirdim ve başlıkta fonksiyonlar hem makro hem de fonksiyon olarak bildirildi. Örneğin

int isdigit(int);

Ayrıca

#define isdigit(c) (_Ctype[(int)(c)] & _DI)

İKİ'nin neden kullanıldığını anlamıyorum?

Ayrıca, kendi özel ctypeüstbilgimi ve uygulamayı yeniden oluşturmaya çalışırsam , yalnızca makroyu kaldırırsam başarılı bir şekilde derleyebilirim (tanımla).

Bu konu kitapta gerçekten açıklanmadı. Birisi açıklayabilir mi lütfen?


C standardında bir derleyiciyi makro olarak uygulamaya zorlayan hiçbir şey yoktur. Makro büyük olasılıkla C'nin satır içi olmadığı eski günlerden kalma bir kalıntıdır. Akıllı bir derleyici, gerekirse açık bir satır içi anahtar kelime olmadan bu işlevi satır içine alabilmelidir. Bu nedenle, işlev benzeri makro sadece oradadır çünkü derleyici derleyici yapmak için mükemmel olmayan biri tarafından uygulanmıştır.

Yanıtlar:


23

Makro, bir işlev çağrısı içermediğinden (varsayılan olarak) daha verimlidir. Sadece bir işaretçi ofseti araması içerdiğinden daha kolay optimize edilebilir.

İşlev çağrısı, program makro tanımı olmadan derlenmiş olsa bile - farklı bir üstbilgi ile derlenmişse veya yalnızca kaynak dosya içinde hileli bir bildirimle aynı kütüphaneye bağlanmaya izin verir. Örneğin, birinin ctype.h dosyasının makroyu içermeyen "geliştirilmiş" sürümüne sahip bir derleyiciniz varsa, işlev çalışma zamanında kullanım için var olmaya devam eder.

Standarda bakarsak:

7.1.4 Kütüphane fonksiyonlarının kullanımı

Üstbilgide bildirilen herhangi bir işlev ek olarak üstbilgide tanımlanan işlev benzeri bir makro olarak da uygulanabilir, bu nedenle bir kitaplık işlevi üstbilgisi dahil edildiğinde açıkça bildirilirse, bildirimin yapılmadığından emin olmak için aşağıda gösterilen tekniklerden biri kullanılabilir böyle bir makrodan etkilenir. Bir işlevin herhangi bir makro tanımı, işlevin adı parantez içine alınarak yerel olarak bastırılabilir, çünkü adın ardından bir makro işlev adının genişlemesini gösteren sol parantez gelmez. Aynı sözdizimsel sebepten dolayı, bir makro olarak tanımlanmış olsa bile bir kütüphane fonksiyonunun adresini almasına izin verilir.

Bu, şöyle yazarsanız:

int b = (isdigit)(c);

veya

int (*f)(int) = &isdigit;
int b = f(c);

makroyu değil, gerçek işlevi çağırıyorsunuz. Ayrıca yasal olarak şunları yazabilirsiniz:

#undef isdigit
int b = isdigit(c);

veya ( #include <ctype.h>doğrudan veya geçişli olmayan bir kaynak dosyada ):

extern int isdigit(int);
int b = isdigit(c);

Program makro tanımı OLMADAN nasıl derlenebilir?
user619818

@ user619818 extern int isdigit(int), örneğin.
ecatmur

Açıkçası, kullanıcı #include <whatever> yok ama bunun yerine int isdigit (int) ekler; uygulama dosyasının en üstünde. Tamam, cevabınızı doğru bir şekilde okuyun.
user619818

Çağrılabilir bir işleve sahip olmak (satır içi makro koduna karşı), python ve perl gibi diğer dillerin de bu işlevlerle arabirim oluşturmasına olanak tanır
technosaurus
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.