6.7.4 Penentu fungsi
Fitur baru C99: Kata inline
kunci, diadaptasi dari C ++, adalah penentu fungsi yang hanya dapat digunakan dalam deklarasi fungsi. Berguna untuk pengoptimalan program yang memerlukan definisi fungsi agar terlihat di lokasi panggilan. (Perhatikan bahwa Standar tidak mencoba menentukan sifat pengoptimalan ini.)
Visibilitas dijamin jika fungsi tersebut memiliki hubungan internal, atau jika memiliki hubungan eksternal dan panggilan berada dalam unit terjemahan yang sama dengan definisi eksternal. Dalam kasus ini, keberadaan
inline
kata kunci dalam deklarasi atau definisi fungsi tidak berpengaruh selain menunjukkan preferensi bahwa panggilan fungsi itu harus dioptimalkan dalam preferensi untuk panggilan fungsi lain yang dideklarasikan tanpa inline
kata kunci.
Visibilitas adalah masalah untuk pemanggilan suatu fungsi dengan linkage eksternal di mana panggilan tersebut berada dalam unit terjemahan yang berbeda dari definisi fungsi. Dalam kasus ini, inline
kata kunci memungkinkan unit terjemahan yang berisi panggilan untuk juga berisi definisi fungsi lokal atau sebaris.
Sebuah program dapat berisi unit terjemahan dengan definisi eksternal, unit terjemahan dengan definisi sebaris, dan unit terjemahan dengan deklarasi tetapi tidak ada definisi untuk suatu fungsi. Panggilan di unit terjemahan terakhir akan menggunakan definisi eksternal seperti biasa.
Definisi sebaris dari suatu fungsi dianggap sebagai definisi yang berbeda dari definisi eksternal. Jika panggilan ke beberapa fungsi func
dengan tautan eksternal terjadi di mana definisi sebaris terlihat, perilakunya sama seperti jika panggilan dilakukan ke fungsi lain, katakanlah
__func
, dengan tautan internal. Program yang sesuai tidak harus bergantung pada fungsi mana yang dipanggil. Ini adalah model sebaris di Standar.
Program yang sesuai tidak boleh bergantung pada implementasi menggunakan definisi inline, juga tidak boleh bergantung pada implementasi yang menggunakan definisi eksternal. Alamat suatu fungsi selalu merupakan alamat yang sesuai dengan definisi eksternal, tetapi bila alamat ini digunakan untuk memanggil fungsi tersebut, definisi sebaris dapat digunakan. Oleh karena itu, contoh berikut mungkin tidak berfungsi seperti yang diharapkan.
inline const char *saddr(void)
{
static const char name[] = "saddr";
return name;
}
int compare_name(void)
{
return saddr() == saddr(); // unspecified behavior
}
Karena implementasi mungkin menggunakan definisi inline untuk salah satu panggilan ke saddr
dan menggunakan definisi eksternal untuk panggilan lainnya, operasi kesetaraan tidak dijamin untuk mengevaluasi ke 1 (true). Ini menunjukkan bahwa objek statis yang didefinisikan dalam definisi sebaris berbeda dari objek yang sesuai dalam definisi eksternal. Hal ini memotivasi kendala bahkan untuk mendefinisikan non- const
objek jenis ini.
Inlining ditambahkan ke Standar sedemikian rupa sehingga dapat diimplementasikan dengan teknologi linker yang ada, dan subset dari C99 inlining kompatibel dengan C ++. Ini dicapai dengan mensyaratkan bahwa tepat satu unit terjemahan yang berisi definisi fungsi sebaris ditetapkan sebagai unit yang memberikan definisi eksternal untuk fungsi tersebut. Karena spesifikasi tersebut hanya terdiri dari deklarasi yang tidak memiliki inline
kata kunci, atau berisi keduanya inline
dan extern
, itu juga akan diterima oleh penerjemah C ++.
Menyebariskan di C99 memang memperluas spesifikasi C ++ dalam dua cara. Pertama, jika sebuah fungsi dideklarasikan
inline
dalam satu unit terjemahan, itu tidak perlu dideklarasikan inline
di setiap unit terjemahan lainnya. Hal ini memungkinkan, misalnya, fungsi pustaka yang menjadi sebaris di dalam pustaka tetapi hanya tersedia melalui definisi eksternal di tempat lain. Alternatif penggunaan fungsi pembungkus untuk fungsi eksternal membutuhkan nama tambahan; dan juga dapat berdampak buruk pada kinerja jika penerjemah tidak benar-benar melakukan substitusi sebaris.
Kedua, persyaratan bahwa semua definisi fungsi inline menjadi "persis sama" diganti dengan persyaratan bahwa perilaku program tidak boleh bergantung pada apakah panggilan diimplementasikan dengan definisi inline yang terlihat, atau definisi eksternal, dari a fungsi. Hal ini memungkinkan definisi sebaris dikhususkan untuk digunakan dalam unit terjemahan tertentu. Misalnya, definisi eksternal dari fungsi pustaka mungkin menyertakan beberapa validasi argumen yang tidak diperlukan untuk panggilan yang dibuat dari fungsi lain di pustaka yang sama. Ekstensi ini memang menawarkan beberapa keuntungan; dan pemrogram yang peduli tentang kompatibilitas dapat dengan mudah mematuhi aturan C ++ yang lebih ketat.
Catatan bahwa itu tidak yang sesuai untuk implementasi untuk memberikan definisi inline fungsi perpustakaan standar dalam header standar karena ini dapat mematahkan beberapa kode warisan yang redeclares standar fungsi perpustakaan setelah termasuk header mereka. Kata inline
kunci hanya dimaksudkan untuk menyediakan cara portabel kepada pengguna untuk menyarankan sebaris fungsi. Karena header standar tidak perlu portabel, implementasi memiliki opsi lain di sepanjang baris:
#define abs(x) __builtin_abs(x)
atau mekanisme non-portabel lainnya untuk menyebariskan fungsi pustaka standar.