Saya memahami bahwa inline
dengan sendirinya adalah saran untuk kompiler, dan atas kebijakannya mungkin atau mungkin tidak sebaris fungsi, dan itu juga akan menghasilkan kode objek yang dapat ditautkan.
Saya pikir itu static inline
melakukan hal yang sama (mungkin atau mungkin tidak sebaris) tetapi tidak akan menghasilkan kode objek yang dapat ditautkan ketika sebaris (karena tidak ada modul lain yang dapat menautkannya).
Di mana yang extern inline
cocok dengan gambar itu?
Asumsikan saya ingin mengganti makro preprocessor dengan fungsi inline dan mensyaratkan agar fungsi ini disisipkan (misalnya, karena menggunakan makro __FILE__
dan __LINE__
yang seharusnya menyelesaikan pemanggil tetapi bukan fungsi yang disebut ini). Artinya, saya ingin melihat kesalahan compiler atau linker jika fungsinya tidak inline. Apakah extern inline
melakukan ini? (Saya berasumsi bahwa, jika tidak, tidak ada cara untuk mencapai perilaku ini selain tetap menggunakan makro.)
Apakah ada perbedaan antara C ++ dan C?
Apakah ada perbedaan antara vendor dan versi kompilator yang berbeda?
sumber
extern inline
tunduk pada aturan satu definisi, dan ini adalah definisi. Namun jika heuristik pengoptimalan yang ditentukan implementasi mengikuti saran untuk menggunakaninline
kata kunci sebagai saran bahwa "panggilan ke fungsi secepat mungkin" (ISO 9899: 1999 §6.7.4 (5),extern inline
hitunganSaya yakin Anda salah paham __FILE__ dan __LINE__ berdasarkan pernyataan ini:
Ada beberapa fase kompilasi, dan preprocessing adalah yang pertama. __FILE__ dan __LINE__ diganti selama fase itu. Jadi pada saat kompilator dapat mempertimbangkan fungsi untuk sebaris, mereka telah diganti.
sumber
Sepertinya Anda mencoba menulis sesuatu seperti ini:
dan berharap Anda akan mendapatkan nilai yang berbeda setiap kali dicetak. Seperti yang dikatakan Don, Anda tidak akan melakukannya, karena __FILE__ dan __LINE__ diimplementasikan oleh preprocessor, tetapi inline diimplementasikan oleh compiler. Jadi, di mana pun Anda memanggil printLocation from, Anda akan mendapatkan hasil yang sama.
Satu- satunya cara Anda bisa membuatnya bekerja adalah dengan membuat printLocation makro. (Ya saya tahu...)
sumber
Situasi dengan sebaris, sebaris statis, dan sebaris eksternal rumit, paling tidak karena gcc dan C99 mendefinisikan arti yang sedikit berbeda untuk perilakunya (dan mungkin juga C ++). Anda dapat menemukan beberapa informasi berguna dan rinci tentang apa yang mereka lakukan di C di sini .
sumber
Makro adalah pilihan Anda di sini daripada fungsi sebaris. Kejadian langka saat makro menguasai fungsi sebaris. Coba yang berikut ini: Saya menulis kode "MACRO MAGIC" ini dan seharusnya berhasil! Diuji di gcc / g ++ Ubuntu 10.04
Untuk beberapa file, tentukan makro ini dalam file header terpisah termasuk yang sama di setiap file c / cc / cxx / cpp. Harap lebih memilih fungsi sebaris atau pengenal konstanta (sesuai tuntutan kasus) daripada makro jika memungkinkan.
sumber
Alih-alih menjawab "apa fungsinya?", Saya menjawab "bagaimana cara membuatnya melakukan apa yang saya inginkan?" Ada 5 jenis sebaris, semuanya tersedia di GNU C89, C99 standar, dan C ++:
selalu sebaris, kecuali ada alamat yang diambil
Menambahkan
__attribute__((always_inline))
ke deklarasi apa pun, lalu gunakan salah satu kasus di bawah ini untuk menangani kemungkinan alamatnya diambil.Anda mungkin tidak boleh menggunakan ini, kecuali jika Anda membutuhkan semantiknya (misalnya untuk mempengaruhi assembly dengan cara tertentu, atau menggunakan
alloca
). Kompiler biasanya lebih tahu dari Anda apakah itu sepadan.sebaris dan memancarkan simbol yang lemah (seperti C ++, alias "buat saja berfungsi")
Perhatikan bahwa ini meninggalkan banyak salinan dari kode yang sama tergeletak di sekitar, dan linker mengambilnya secara sewenang-wenang.
sebaris, tetapi tidak pernah memancarkan simbol apa pun (meninggalkan referensi eksternal)
memancarkan selalu (untuk satu TU, untuk menyelesaikan yang sebelumnya)
Versi yang diisyaratkan memancarkan simbol yang lemah di C ++, tetapi simbol yang kuat di kedua dialek C:
Atau Anda dapat melakukannya tanpa petunjuk, yang memancarkan simbol yang kuat dalam kedua bahasa:
Umumnya, Anda tahu bahasa apa TU Anda saat memberikan definisi, dan mungkin tidak perlu banyak penyebarisan.
sebaris dan memancarkan di setiap TU
Untuk semua ini kecuali
static
satu, Anda dapat menambahkanvoid foo(void)
deklarasi di atas. Ini membantu dengan "praktik terbaik" dalam menulis header yang bersih, kemudian#include
membuat file terpisah dengan definisi sebaris. Kemudian, jika menggunakan sebaris gaya C,#define
beberapa makro berbeda dalam satu TU khusus untuk memberikan definisi di luar baris.Jangan lupa
extern "C"
jika header mungkin digunakan dari C dan C ++!sumber
nm
padanannya.