Mengapa orang sering menggunakan __ (garis bawah ganda) di C ++

93

Saya telah melihat-lihat beberapa kode C ++ open source dan melihat banyak skor double under yang digunakan dalam kode, terutama di awal nama variabel.

return __CYGWIN__;

Hanya bertanya-tanya apakah ada alasan untuk ini, atau hanya beberapa gaya kode orang? Saya akan berpikir bahwa saya membuatnya sulit untuk dibaca.

Nathan W.
sumber
2
Mengapa sulit dibaca? Ini dirancang sebagian besar sebagai pembatas, seperti tanda kutip. Seingat saya, ini terutama digunakan untuk konstanta bawaan.
Matthew Scharley
1
Tidak, ini bukan pembatas. Garis bawah digunakan untuk membedakan nama yang dicadangkan untuk implementasi dari nama yang dapat digunakan kode sumber pengguna. Pengguna dapat melakukan #define FOO 1tetapi mereka tidak boleh melakukannya #define __FOO__ 1dan oleh karena itu implementasinya bebas menggunakan nama __FOO__untuk makro, variabel, fungsi, dll.
Jonathan Wakely
Saya pikir yang dimaksud Matius adalah pembatas gaya / visual, bukan secara fungsional. Yang merupakan hipotesis yang menarik, tetapi salah mengingat apa yang telah saya baca sebelumnya dan jawaban Jonathan.
JMI MADISON

Jawaban:

127

Dari Pemrograman di C ++, Aturan dan Rekomendasi :

Penggunaan dua garis bawah (`__ ') dalam pengidentifikasi disediakan untuk penggunaan internal kompiler sesuai dengan standar ANSI-C.

Garis bawah (`_ ') sering digunakan dalam nama fungsi perpustakaan (seperti" _main "dan" _exit "). Untuk menghindari benturan, jangan mulai pengenal dengan garis bawah.

maccullt.dll
sumber
1
Panduan itu sepertinya ditulis sebelum namespacediperkenalkan.
cz
itu juga dari imperial college london bukan dari standar C ++; itu mungkin saran yang bagus.
stucash
1
@cz Namespaces tidak relevan. Header sistem dapat menentukan nama makro yang dimulai dengan garis bawah misalnya _main.
martinkunev
49

Kecuali mereka merasa bahwa mereka adalah "bagian dari implementasi", yaitu pustaka standar, maka mereka seharusnya tidak melakukannya.

Aturannya cukup spesifik, dan sedikit lebih rinci daripada yang disarankan beberapa orang lain.

Semua pengenal yang berisi garis bawah ganda atau dimulai dengan garis bawah yang diikuti dengan huruf besar dicadangkan untuk penggunaan implementasi di semua cakupan, yaitu mungkin digunakan untuk makro.

Selain itu, semua pengenal lain yang dimulai dengan garis bawah (yaitu tidak diikuti oleh garis bawah atau huruf besar lainnya) dicadangkan untuk implementasi pada lingkup global. Ini berarti Anda dapat menggunakan pengenal ini di ruang nama Anda sendiri atau dalam definisi kelas.

Inilah sebabnya mengapa Microsoft menggunakan nama fungsi dengan garis bawah di depan dan semua dalam huruf kecil untuk banyak fungsi pustaka runtime inti mereka yang bukan bagian dari standar C ++. Nama fungsi ini dijamin tidak akan berbenturan dengan fungsi C ++ standar atau fungsi kode pengguna.

CB Bailey
sumber
1
Di C ++ saya hanya melihat [lex.name] dan untuk nama global [global.names]. Bisakah Anda memberikan referensi? terima kasih
a.lasram
36

Menurut Standar C ++, pengenal yang dimulai dengan satu garis bawah disediakan untuk pustaka. Pengenal yang dimulai dengan dua garis bawah disediakan untuk vendor compiler.

James Curran
sumber
18
Lebih dari itu: pengenal yang mengandung garis bawah ganda di mana saja di dalamnya dicadangkan. 17.4.3.1.2
Steve Jessop
Di C ++ saya hanya melihat [lex.name] dan untuk nama global [global.names]. Bisakah Anda memberikan referensi? terima kasih
a.lasram
10

Komentar di atas benar. __Symbol__umumnya merupakan token ajaib yang disediakan oleh vendor compiler (atau preprocessor) Anda yang membantu. Mungkin yang paling banyak digunakan adalah __FILE__dan __LINE__, yang diperluas oleh praprosesor C untuk menunjukkan nama file dan nomor baris saat ini. Itu berguna ketika Anda ingin mencatat semacam kegagalan pernyataan program, termasuk lokasi kesalahan secara tekstual.

rawa
sumber
8

Itu adalah sesuatu yang tidak seharusnya Anda lakukan dalam kode 'normal'. Ini memastikan bahwa kompiler dan pustaka sistem dapat menentukan simbol yang tidak akan bertabrakan dengan milik Anda.

Menkboy
sumber
4

Garis bawah ganda dicadangkan untuk implementasi

Jawaban dengan suara terbanyak mengutip Pemrograman di C ++: Aturan dan Rekomendasi :

"Penggunaan dua garis bawah (` __ ') dalam pengidentifikasi disediakan untuk penggunaan internal kompiler sesuai dengan standar ANSI-C. "

Namun, setelah membaca beberapa standar C ++ dan C, saya tidak dapat menemukan penyebutan garis bawah yang dibatasi hanya untuk penggunaan internal kompiler. Standar tersebut lebih umum, dengan menggunakan garis bawah ganda untuk implementasinya .

C ++

C ++ (draf kerja saat ini, diakses 2019-5-26) menyatakan dalam lex.name:

  • Setiap pengenal yang berisi garis bawah ganda __ atau diawali dengan garis bawah yang diikuti dengan huruf besar dicadangkan untuk implementasi untuk penggunaan apa pun.
  • Setiap pengenal yang dimulai dengan garis bawah dicadangkan untuk implementasi untuk digunakan sebagai nama di namespace global.

C

Meskipun pertanyaan ini khusus untuk C ++, saya telah mengutip bagian yang relevan dari C standar 99 dan 17:

C99 bagian 7.1.3

  • Semua pengenal yang dimulai dengan garis bawah dan huruf besar atau garis bawah lainnya selalu disediakan untuk penggunaan apa pun.
  • Semua pengenal yang dimulai dengan garis bawah selalu disediakan untuk digunakan sebagai pengenal dengan cakupan file di ruang nama biasa dan tag.

C17 mengatakan hal yang sama dengan C99.

Apa implementasinya ?

Untuk C / C ++, implementasi secara longgar mengacu pada kumpulan sumber daya yang diperlukan untuk menghasilkan file yang dapat dieksekusi dari sumber pengguna. Ini termasuk:

  • preprocessor
  • penyusun
  • linker
  • perpustakaan standar

Contoh implementasi

Ada sejumlah implementasi C ++ berbeda yang disebutkan di Wikipedia . (tanpa tautan tautan, ctrl + f "implementasi")

Berikut adalah contoh implementasi Digital Mars 'C / C ++ yang mencadangkan beberapa kata kunci untuk fitur miliknya.

RemarkableBucket
sumber
3

Selain pustaka yang ditanggapi banyak orang, Beberapa orang juga memberi nama makro atau #define values ​​untuk digunakan dengan preprocessor. Ini akan membuatnya lebih mudah untuk dikerjakan, dan mungkin telah memungkinkan bug di kompiler lama untuk diselesaikan.

Seperti yang disebutkan orang lain, ini membantu mencegah tabrakan nama dan membantu menggambarkan antara variabel perpustakaan dan variabel Anda sendiri.

Sqeaky
sumber