Pertanyaan Apa aturan tentang penggunaan underscore di identifier C ++?


Ini umum di C + + untuk memberi nama variabel anggota dengan beberapa jenis awalan untuk menunjukkan fakta bahwa mereka adalah variabel anggota, daripada variabel atau parameter lokal. Jika Anda datang dari latar belakang MFC, Anda mungkin akan menggunakannya m_foo. Saya juga sudah melihat myFoo kadang.

C # (atau mungkin saja .NET) sepertinya merekomendasikan hanya menggunakan garis bawah, seperti pada _foo. Apakah ini diperbolehkan oleh standar C ++?


800
2017-10-23 07:02


asal


Jawaban:


Aturan (yang tidak berubah dalam C ++ 11):

  • Dicadangkan dalam cakupan apa pun, termasuk untuk digunakan sebagai makro implementasi:
    • pengidentifikasi yang dimulai dengan garis bawah segera diikuti dengan huruf besar
    • pengidentifikasi berisi garis bawah yang bersebelahan (atau "garis bawah ganda")
  • Dicadangkan dalam namespace global:
    • pengidentifikasi dimulai dengan garis bawah
  • Juga, semuanya di std namespace dicadangkan. (Anda diizinkan untuk menambahkan spesialisasi template.)

Dari Standar C ++ 2003:

17.4.3.1.2 Nama global [lib.global.names]

Kumpulan nama dan tanda fungsi tertentu selalu disediakan untuk implementasi:

  • Setiap nama yang berisi garis bawah ganda (__) atau dimulai dengan garis bawah diikuti dengan huruf besar (2.11) dicadangkan untuk implementasi untuk penggunaan apa pun.
  • Setiap nama yang diawali dengan underscore disediakan untuk implementasi untuk digunakan sebagai nama dalam namespace global.165

165) Nama-nama seperti itu juga disediakan dalam namespace ::std (17.4.3.1).

Karena C ++ didasarkan pada standar C (1.1 / 2, C ++ 03) dan C99 adalah referensi normatif (1.2 / 1, C ++ 03) ini juga berlaku, dari Standar C 1999:

7.1.3 Pengenal yang dilindungi

Setiap tajuk menyatakan atau mendefinisikan semua pengidentifikasi yang tercantum dalam subklausul terkait, dan   opsional mendeklarasikan atau mendefinisikan pengenal yang tercantum dalam subclause dan identifier petunjuk terkait perpustakaan di masa mendatang yang selalu disediakan untuk penggunaan apa pun atau untuk digunakan sebagai pengidentifikasi lingkup file.

  • Semua pengidentifikasi yang dimulai dengan garis bawah dan huruf besar atau lainnya   underscore selalu disediakan untuk penggunaan apa pun.
  • Semua pengidentifikasi yang dimulai dengan garis bawah selalu dicadangkan untuk digunakan sebagai pengenal   dengan ruang lingkup file di kedua ruang nama biasa dan tag.
  • Setiap nama makro dalam salah satu dari subklausa berikut (termasuk pustaka mendatang   arah) dicadangkan untuk digunakan sebagaimana ditentukan jika ada header terkait disertakan;   kecuali dinyatakan lain secara eksplisit (lihat 7.1.4).
  • Semua pengidentifikasi dengan hubungan eksternal dalam salah satu dari subklausa berikut (termasuk   arah perpustakaan masa depan) selalu disediakan untuk digunakan sebagai pengidentifikasi dengan eksternal   hubungan.154
  • Setiap pengenal dengan lingkup file tercantum dalam salah satu dari subklausa berikut (termasuk   arah perpustakaan masa depan) disediakan untuk digunakan sebagai nama makro dan sebagai pengidentifikasi dengan   ruang lingkup file di ruang nama yang sama jika ada header terkait disertakan.

Tidak ada pengenal lain yang dilindungi. Jika program menyatakan atau mendefinisikan pengenal dalam a   konteks di mana itu dilindungi (selain yang diizinkan oleh 7.1.4), atau menentukan yang dilindungi undang-undang   identifier sebagai nama makro, perilaku tidak terdefinisi.

Jika program menghapus (dengan #undef) definisi makro apa pun dari identifier di awal   grup yang tercantum di atas, perilaku tidak terdefinisi.

154) Daftar pengidentifikasi cadangan dengan tautan eksternal termasuk errno, math_errhandling, setjmp, dan va_end.

Pembatasan lain mungkin berlaku. Sebagai contoh, standar POSIX menyimpan banyak pengidentifikasi yang mungkin muncul dalam kode normal:

  • Nama dimulai dengan modal E mengikuti digit atau huruf besar:
    • dapat digunakan untuk nama kode kesalahan tambahan.
  • Nama yang dimulai dengan baik is atau to diikuti dengan huruf kecil
    • dapat digunakan untuk pengujian karakter tambahan dan fungsi konversi.
  • Nama yang dimulai dengan LC_ diikuti dengan huruf besar
    • dapat digunakan untuk makro tambahan yang menentukan atribut lokal.
  • Nama dari semua fungsi matematika yang ada dengan akhiran f atau l dilindungi undang-undang
    • untuk fungsi terkait yang beroperasi pada float dan argumen ganda panjang, masing-masing.
  • Nama yang dimulai dengan SIG diikuti dengan huruf besar yang dicadangkan
    • untuk nama sinyal tambahan.
  • Nama yang dimulai dengan SIG_ diikuti dengan huruf besar yang dicadangkan
    • untuk tindakan sinyal tambahan.
  • Nama yang diawali dengan str, mem, atau wcs diikuti dengan huruf kecil yang disediakan
    • untuk fungsi string dan larik tambahan.
  • Nama yang diawali dengan PRI atau SCN diikuti dengan huruf kecil atau X dilindungi undang-undang
    • untuk makro penentu format tambahan
  • Nama yang diakhiri dengan _t dilindungi undang-undang
    • untuk nama tipe tambahan.

Meskipun menggunakan nama-nama ini untuk tujuan Anda sendiri sekarang mungkin tidak menimbulkan masalah, mereka meningkatkan kemungkinan konflik dengan versi standar yang akan datang.


Secara pribadi saya tidak memulai pengidentifikasi dengan garis bawah. Tambahan baru untuk aturan saya: Jangan gunakan garis bawah ganda di mana saja, yang mudah karena saya jarang menggunakan underscore.

Setelah melakukan penelitian pada artikel ini saya tidak lagi mengakhiri pengidentifikasi saya _t karena ini disediakan oleh standar POSIX.

Aturan tentang pengidentifikasi yang diakhiri dengan _t mengejutkan saya banyak. Saya pikir itu adalah standar POSIX (belum pasti) mencari klarifikasi dan bab dan ayat resmi. Ini dari Panduan GNU libtool, daftar nama yang dicadangkan.

CesarB memberikan tautan berikut ke POSIX 2004 simbol dan catatan yang dilindungi 'bahwa banyak prefiks dan sufiks lain yang dilindungi ... dapat ditemukan di sana'. Itu POSIX 2008 simbol yang dilindungi didefinisikan di sini. Pembatasan agak lebih bernuansa daripada yang di atas.


739
2017-10-23 07:27



Aturan untuk menghindari tabrakan nama sama-sama dalam standar C ++ (lihat buku Stroustrup) dan disebutkan oleh C ++ gurus (Sutter, dll.).

Aturan pribadi

Karena saya tidak mau berurusan dengan kasus, dan menginginkan aturan sederhana, saya telah merancang sebuah pribadi yang sederhana dan benar:

Saat menamai simbol, Anda akan menghindari tabrakan dengan pustaka kompilator / OS / standar jika Anda:

  • jangan pernah memulai simbol dengan garis bawah
  • jangan pernah menyebutkan simbol dengan dua garis bawah berturut-turut di dalamnya.

170
2017-10-23 07:06



Dari MSDN:

Penggunaan dua karakter garis bawah berurutan (__) di awal pengidentifikasi, atau garis bawah tunggal yang diikuti oleh huruf kapital, dicadangkan untuk implementasi C ++ di semua cakupan. Anda harus menghindari menggunakan satu garis bawah utama diikuti dengan huruf kecil untuk nama dengan lingkup file karena kemungkinan konflik dengan pengidentifikasi cadangan saat ini atau masa depan.

Ini berarti bahwa Anda dapat menggunakan garis bawah tunggal sebagai awalan variabel anggota, asalkan diikuti oleh huruf huruf kecil.

Ini rupanya diambil dari bagian 17.4.3.1.2 standar C ++, tetapi saya tidak dapat menemukan sumber asli untuk online standar penuh.

Lihat juga pertanyaan ini.


28
2017-11-14 20:03



Adapun bagian lain dari pertanyaan, itu umum untuk menempatkan garis bawah pada akhir dari nama variabel untuk tidak berbenturan dengan internal apa pun.

Saya melakukan ini bahkan di dalam kelas dan ruang nama karena saya kemudian hanya perlu mengingat satu aturan (dibandingkan dengan "pada akhir nama dalam lingkup global, dan awal nama di tempat lain").


21
2017-10-23 07:05



Ya, setrip bawah dapat digunakan di mana saja dalam pengenal. Saya percaya aturannya adalah: apapun dari a-z, A-Z, _ di karakter pertama dan mereka + 0-9 untuk karakter berikut.

Garisbesar awalan adalah hal yang umum dalam kode C - garis bawah tunggal berarti "pribadi", dan garis bawah ganda biasanya disediakan untuk digunakan oleh kompilator.


2