Yanıtlar:
inline
derleyiciye, gerçek bir çağrı yürütmek yerine işlev içeriğini çağıran koda yerleştirmeyi denemesini söyler.
Sıklıkla çağrılan küçük işlevler için büyük bir performans farkı yaratabilir.
Ancak, bu sadece bir "ipucu" ve derleyici bunu göz ardı edebilir ve çoğu derleyici, mümkün olduğu durumlarda, optimizasyonların bir parçası olarak anahtar kelime kullanılmadığında bile "satır içi" yapmaya çalışacaktır.
Örneğin:
static int Inc(int i) {return i+1};
.... // some code
int i;
.... // some more code
for (i=0; i<999999; i = Inc(i)) {/*do something here*/};
Bu sıkı döngü, her yinelemede bir işlev çağrısı gerçekleştirir ve işlev içeriği aslında derleyicinin çağrıyı gerçekleştirmek için koyması gereken koddan önemli ölçüde daha azdır. inline
temelde derleyiciye yukarıdaki kodu eşdeğerine dönüştürmesi talimatını verecektir:
int i;
....
for (i=0; i<999999; i = i+1) { /* do something here */};
Gerçek işlev çağrısını atlama ve geri dönme
Açıkçası bu, gerçek bir kod parçası değil, noktayı gösteren bir örnektir.
static
kapsamı ifade eder. C'de bu, işlevin / değişkenin yalnızca aynı çeviri birimi içinde kullanılabileceği anlamına gelir.
static
(olsun veya olmasın inline
) başlıkta gayet iyi olabilir, neden olmasın. Şablonlar C ++ içindir, bu soru C ile ilgilidir
inline
iyi bir stildir, imo
inline
vermez . Yalnızca programcının işlev gövdesini ODR ihlali olmadan çoklu çeviri birimlerine dahil etmesine izin verir. Bunun bir yan etkisi 's markaları mümkün derleyicisi için, bu zaman olacağı ediyorum işlevi satır içi aslında bunu yapmak için.
Varsayılan olarak, bir satır içi tanım yalnızca mevcut çeviri biriminde geçerlidir.
Depolama sınıfı ise extern
, tanımlayıcının harici bağlantısı vardır ve satır içi tanım da harici tanımı sağlar.
Depolama sınıfı ise static
, tanımlayıcının dahili bağlantısı vardır ve satır içi tanım diğer çeviri birimlerinde görünmezdir.
Depolama sınıfı belirtilmemişse, satır içi tanım yalnızca geçerli çeviri biriminde görülebilir, ancak tanımlayıcının hala harici bir bağlantısı vardır ve farklı bir çeviri biriminde bir dış tanım sağlanmalıdır. İşlev mevcut çeviri birimi içinde çağrılırsa, derleyici satır içi veya harici tanımı kullanmakta serbesttir.
Derleyici, tanımı mevcut çeviri biriminde görülebilen (ve bağlantı zamanı optimizasyonları sayesinde, farklı çeviri birimlerinde bile olsa, satır içi (ve satır içi değil) herhangi bir işlevi satır içi (ve satır içi olmamak) konusunda özgür olduğundan, C standardı gerçekten hesaba katmaz. that), çoğu pratik amaç için, static
ve static inline
işlev tanımları arasında hiçbir fark yoktur .
inline
(Gibi belirteci register
depolama sınıfına) sadece bir derleyici ipucu ve derleyici tümüyle görmezden serbesttir. Standartlara uyumlu, optimize etmeyen derleyiciler yalnızca yan etkilerini dikkate almalıdır ve derleyicilerin optimize edilmesi, bu optimizasyonları açık ipuçları olsun veya olmasın yapacaktır.
inline
ve register
programcı optimizasyonları imkansız hale getirecek kod yazdığında derleyiciye hatalar atması talimatını verdikleri için faydasız değildir: Harici bir inline
tanım iç bağlantıya sahip tanımlayıcılara referans veremez (çünkü bunlar farklı bir çeviri biriminde mevcut olmayacaktır) veya statik depolama süresi olan değiştirilebilir yerel değişkenler tanımlayın (çünkü bunlar, çeviri birimleri arasında durumu paylaşmazlar) ve register
-kalifiye değişkenlerin adreslerini alamazsınız.
Kişisel olarak, üstbilgi dosyalarına işlev tanımlarını koymanın ana nedeni onları satır içi yapmak olduğundan, static
işlev tanımlarını başlıklarda işaretlemek inline
için de kullanıyorum.
Genel olarak, başlıklardaki bildirimlere ek olarak yalnızca static inline
işlev ve static const
nesne tanımlarını kullanıyorum extern
.
Daha önce inline
depolama sınıfından farklı bir işlev yazmadım static
.
inline
Gerçekte satır içi yapmaya uygulanmış gibi konuşan herhangi bir cevap yanıltıcıdır ve muhtemelen yanlıştır. Hiçbir modern derleyici bunu satır içi bir ipucu olarak kullanmaz veya bir işlevin satır içi olarak yazılmasını sağlamak için bunu gerektirmez.
static
ve arasındaki anlamsal farkı anlamadım static inline
. Her ikisi de tanımı diğer çeviri birimlerine görünmez kılar. Peki static inline
bunun yerine yazmak için mantıklı bir neden ne olabilir static
?
GCC ile olan deneyimlerime dayanarak bunu biliyorum static
ve static inline
derleyicinin kullanılmayan işlevler hakkında nasıl uyarılar verdiğini bir şekilde farklılaştırıyorum. Daha doğrusu, static
işlevi bildirdiğinizde ve mevcut çeviri biriminde kullanılmadığında, derleyici kullanılmayan işlev hakkında uyarı üretir, ancak bu uyarıyı olarak değiştirerek engelleyebilirsiniz static inline
.
Bu nedenle, bunun static
çeviri birimlerinde kullanılması gerektiğini ve kullanılmayan işlevleri bulmak için derleyicinin fazladan kontrolünden faydalanması gerektiğini düşünüyorum . Ve static inline
uyarı veren olmadan kaplı (nedeniyle dış bağlantı bulunmadığı için) olabilir işlevleri sağlamak için başlık dosyalarında kullanılmalıdır.
Ne yazık ki bu mantık için herhangi bir kanıt bulamıyorum. GCC belgelerinden bile, inline
kullanılmayan işlev uyarılarını engellediğine karar veremedim . Birisi bunun açıklamasına bağlantılar paylaşırsa memnun olurum.
warning: unused function 'function' [clang-diagnostic-unused-function]
bir static inline
işlev var clang-tidy
. Ama kesinlikle, bu en iyi açıklamalardan biri ve static
& inline
!
C'de, static
tanımladığınız işlev veya değişkenin yalnızca bu dosyada kullanılabileceği anlamına gelir (yani derleme birimi)
Yani, static inline
yalnızca bu dosyada kullanılabilen satır içi işlevi anlamına gelir.
DÜZENLE:
Derleme birimi Çeviri Birimi olmalıdır
the compile unit
translation unit
Dil düzeyinde değil, popüler uygulama düzeyinde olan bir fark: gcc'nin belirli sürümleri, static inline
varsayılan olarak referans alınmayan işlevleri çıktıdan kaldırır , ancak static
başvurulmasa bile düz işlevleri korur. Emin bu geçerli olduğu hangi versiyonları değilim, ama pratik bir bakış açısından o her zaman kullanmak iyi bir fikir olabilir demektir inline
için static
başlıklardaki fonksiyonlar.
inline
Tanım olarak kullanmaya ne dersiniz ? Bunu extern
işlevler için kullanmamayı da ima ediyor musunuz ?
attribute((used))
asm'nin başka türlü başvurulmayan static
işlevlere ve verilere başvurmasına izin vermek için geçmişine ve kullanımına bakarak öğrenebilirsiniz .
static
kapsamı ifade eder. C'de bu, işlevin / değişkenin yalnızca aynı çeviri birimi içinde kullanılabileceği anlamına gelir.