Apa konvensi penamaan yang paling umum di C?

126

Apa konvensi penamaan yang biasa digunakan di C? Saya tahu setidaknya ada dua:

  1. GNU / linux / K&R dengan fungsi huruf_kecil
  2. ? nama? dengan fungsi UpperCaseFoo

Saya berbicara tentang C hanya di sini. Sebagian besar proyek kami adalah sistem tertanam kecil di mana kami menggunakan C.

Inilah yang saya rencanakan untuk digunakan untuk proyek saya berikutnya:


C Konvensi Penamaan

Struct              TitleCase
Struct Members      lower_case or lowerCase

Enum                ETitleCase
Enum Members        ALL_CAPS or lowerCase

Public functions    pfx_TitleCase (pfx = two or three letter module prefix)
Private functions   TitleCase
Trivial variables   i,x,n,f etc...
Local variables     lower_case or lowerCase
Global variables    g_lowerCase or g_lower_case (searchable by g_ prefix)
JeffV
sumber
7
Saya tidak akan memaksakan awalan 'g_' pada variabel global; Saya akan menerapkan nama yang bermakna (jadi client_locale dan bukan cl_lc sebagai nama variabel global). Klasik C tidak menggunakan tas unta; Saya telah menulis kode dalam camel-case di C, dan itu terlihat aneh (jadi saya tidak melakukannya lagi). Meskipun demikian, itu tidak salah - dan konsistensi lebih penting daripada konvensi mana yang digunakan. Hindari typedef yang merangkum petunjuk struktur; pertimbangkan standar C - 'FILE *' dieja dengan demikian, bukan FILE_PTR.
Jonathan Leffler
2
@Jonathan Leffler, ada apa dengan g_ untuk menandakan global? Dalam sistem tertanam, saya mengalami masalah sebelumnya di mana sulit untuk melacak dependensi antar-modul melalui vars global dan g_somevar eksternal. Saya pribadi berpikir itu umumnya adalah ide yang buruk, tetapi hal semacam ini biasanya dilakukan karena alasan kinerja. Misalnya, bendera global yang disetel oleh interupsi yang menunjukkan bahwa data sudah siap.
JeffV
2
Untuk apa nilainya, konvensi penamaan ini sebagian besar diambil dari konvensi API PalmOS. Juga, ini mirip dengan konvensi yang digunakan dalam buku O'Reilly: "Programming Embedded Systems with C and GNU Development Tools". Secara pribadi, saya suka TitleCase dalam nama fungsi. Saya berpikir untuk menggunakan lowerCamelCase dalam fungsi tautan internal (yang saya sebut pribadi dalam pertanyaan saya).
JeffV
3
@ Chris Lutz, saya setuju, dengan sepenuh hati. Di mana pun kemungkinan vars disimpan pada ruang lingkup yang paling sempit. Perhatikan bahwa sebenarnya ada tiga cakupan yang sedang kita diskusikan: lokal ke fungsi, lokal ke modul (tidak ada hubungan eksternal ke variabel) dan global dengan hubungan eksternal. Biasanya memiliki variabel "global to a module" dalam sistem tertanam. Oleh karena itu, perhatian harus diberikan untuk mengidentifikasi global dengan keterkaitan eksternal sehingga dapat dijaga seminimal mungkin dan interaksi modul dipahami. Di sinilah awalan "g_" berguna.
JeffV
46
Saya suka mengawali variabel global dengan //.
plafer

Jawaban:

128

Hal terpenting di sini adalah konsistensi. Karena itu, saya mengikuti konvensi pengkodean GTK +, yang dapat diringkas sebagai berikut:

  1. Semua makro dan konstanta dalam huruf kapital: MAX_BUFFER_SIZE, TRACKING_ID_PREFIX.
  2. Nama struktur dan typedef dalam unta: GtkWidget, TrackingOrder.
  3. Fungsi yang beroperasi pada struct: gaya C klasik: gtk_widget_show(), tracking_order_process().
  4. Petunjuk: tidak ada yang mewah di sini: GtkWidget *foo, TrackingOrder *bar.
  5. Variabel global: jangan gunakan variabel global. Mereka jahat.
  6. Fungsi yang ada, tetapi tidak boleh dipanggil secara langsung, atau memiliki kegunaan yang tidak jelas, atau apa pun: satu atau beberapa garis bawah di awal: _refrobnicate_data_tables(), _destroy_cache().
axel_c
sumber
13
Pada poin enam saya lebih suka menggunakan staticdan melewatkan awalan modul, jadi jika gtk_widget_show()fungsi dengan ruang lingkup file itu akan menjadi sederhana widget_show()dengan kelas penyimpanan statis ditambahkan.
Agustus Karlstrom
27
Catatan tambahan tentang poin 6: standar C memiliki beberapa aturan tentang pemesanan nama yang dimulai dengan _implementasi dan penggunaan di masa mendatang. Ada beberapa pengecualian untuk nama yang diawali dengan _tetapi menurut saya tidak sepadan dengan kesulitan menghafalnya. Aturan yang aman untuk dilalui adalah jangan pernah menggunakan nama yang dimulai dengan _kode Anda. Entri C FAQ yang relevan: c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=decl#namespace
jw013
5
# 2 lebih khusus lagi case unta atas atau case pascal . Camel case atau lower case menggunakan huruf kecil pada huruf pertama.
Clint Pachl
9
Bagaimana dengan variabel multi-kata lokal? my_var atau myVar?
Dean Gurvitz
4
Global variables: just don't use global variables. They are evil.- kecuali Anda sedang mengerjakan proyek tertanam dan Anda memiliki RAM 1024 byte dan CPU 8MHz.
Kamil
30

"Struct pointers" bukanlah entitas yang membutuhkan klausul konvensi penamaan untuk menutupinya. Mereka adil struct WhatEver *. JANGAN menyembunyikan fakta bahwa ada pointer yang terlibat dengan typedef yang pintar dan "jelas". Ini tidak memiliki tujuan, lebih lama untuk mengetik, dan menghancurkan keseimbangan antara deklarasi dan akses.

beristirahat
sumber
29
+1 untuk hal-hal "jangan sembunyikan petunjuk" - meskipun jawaban ini tidak menjawab sebagian besar pertanyaan (belum).
Jonathan Leffler
1
@unwind, saya cenderung setuju. Namun, terkadang sebuah pointer tidak dimaksudkan untuk menjadi dereferensi eksternal dan itu lebih merupakan pegangan bagi konsumen daripada sebuah pointer yang sebenarnya ke struct yang akan mereka gunakan. Untuk itulah saya meninggalkan TitleCasePtr. struktur typedef {bidang} MyStruct, * MyStructPtr;
JeffV
Saya menghapus TitleCasePtr, itu mengganggu dari pertanyaan sebenarnya.
JeffV
1
-1 dari saya karena deklarasi tipe pointer mengurangi kekacauan, terutama dalam tanda tangan fungsi dan "ketidakseimbangan" antara deklarasi dan akses hanya muncul di file implementasi - klien tidak (seharusnya) mengakses anggota bidang secara langsung.
Agustus Karlstrom
1
@AgusSaputra. Saya tidak mengerti apa yang "hanya" tentang file implementasi, bukankah kode itu juga? Saya tidak menafsirkan pertanyaan itu hanya sebagai tentang nama "luar". Semua kode adalah "implementasi" di tingkat tertentu.
bersantai
17

Pertama C tidak memiliki fungsi publik / pribadi / virtual. Itu C ++ dan memiliki konvensi yang berbeda. Di C biasanya Anda memiliki:

  • Konstanta dalam ALL_CAPS
  • Menggarisbawahi untuk membatasi kata dalam struct atau nama fungsi, Anda hampir tidak pernah melihat kasus unta di C;
  • struct, typedefs, unions, members (of unions and structs) dan nilai enum biasanya dalam huruf kecil (menurut pengalaman saya) daripada konvensi C ++ / Java / C # / etc untuk membuat huruf pertama menjadi kapital tapi saya kira itu mungkin di C juga.

C ++ lebih kompleks. Saya telah melihat campuran yang nyata di sini. Kasus unta untuk nama kelas atau huruf kecil + garis bawah (kasus unta lebih umum menurut pengalaman saya). Struktur jarang digunakan (dan biasanya karena perpustakaan memerlukannya, jika tidak, Anda akan menggunakan kelas).

cletus
sumber
@cletus, saya menyadari itu. Yang saya maksud dengan pribadi adalah fungsi yang tidak diekspos secara eksternal di header modul dan tidak dimaksudkan untuk digunakan oleh kode di luar modul. Publik akan menjadi fungsi API modul yang dimaksudkan untuk digunakan secara eksternal.
JeffV
3
Anda dapat menganggap fungsi statis sebagai pribadi; pertanyaannya tidak menyebutkan virtual. Tapi +1 untuk 'jarang melihat tas unta di C'.
Jonathan Leffler
2
Saya pikir Jeff dimaksudkan external linkageuntuk "acara publik" dan internal linkage"acara pribadi".
pmg
1
Saya telah melihat konstanta yang dimulai dengan ak serta di: kBufferSize. Tidak yakin dari mana asalnya.
JeffV
2
ALL_CAPSsering digunakan untuk nilai enum juga.
kafe
14

Anda tahu, saya suka membuatnya sederhana, tapi jelas ... Jadi inilah yang saya gunakan, di C:

  • Sepele Variabel : i,n,c(. Hanya satu huruf Jika satu huruf tidak jelas, kemudian membuatnya Variabel lokal), dll ...
  • Variabel Lokal :lowerCamelCase
  • Variabel Global :g_lowerCamelCase
  • Variabel Const :ALL_CAPS
  • Variabel Pointer : tambahkan a p_ke awalan. Untuk variabel global gp_var, untuk variabel lokal p_var, untuk variabel konst p_VAR. Jika penunjuk jauh digunakan, gunakan an fp_sebagai pengganti p_.
  • Structs : ModuleCamelCase(Module = nama modul lengkap, atau singkatan 2-3 huruf, tapi masih masuk CamelCase.)
  • Variabel Anggota Struct :lowerCamelCase
  • Enum :ModuleCamelCase
  • Nilai Enum :ALL_CAPS
  • Fungsi Umum :ModuleCamelCase
  • Fungsi Pribadi :CamelCase
  • Makro :CamelCase

Saya mengetikkan struct saya, tetapi menggunakan nama yang sama untuk tag dan typedef tersebut. Tag tidak dimaksudkan untuk digunakan secara umum. Sebaliknya lebih disukai menggunakan typedef tersebut. Saya juga meneruskan mendeklarasikan typedef di header modul publik untuk enkapsulasi dan agar saya dapat menggunakan nama typedef dalam definisi.

struct Contoh Lengkap :

typdef struct TheName TheName;
struct TheName{
    int var;
    TheName *p_link;
};
SeanRamey
sumber
Saya tidak tahu apa-apa tentang kerangka qt, tetapi Anda dapat menulis kode Anda dalam format gaya apa pun yang Anda inginkan. Tidak ada yang menghalangi Anda darinya, sejauh yang saya tahu.
SeanRamey
10

Pengkodean di C #, java, C, C ++ dan tujuan C pada saat yang sama, saya telah mengadopsi konvensi penamaan yang sangat sederhana dan jelas untuk menyederhanakan hidup saya.

Pertama-tama, ini bergantung pada kekuatan IDE modern (seperti eclipse, Xcode ...), dengan kemungkinan untuk mendapatkan informasi cepat dengan mengarahkan atau klik ctrl ... Menerima itu, saya menghentikan penggunaan awalan apa pun, sufiks dan penanda lain yang hanya diberikan oleh IDE.

Kemudian, konvensi:

  • Nama apa pun HARUS merupakan kalimat yang dapat dibaca menjelaskan apa yang Anda miliki. Seperti "ini konvensi saya".
  • Kemudian, 4 metode untuk mendapatkan konvensi dari sebuah kalimat:
    1. THIS_IS_MY_CONVENTION untuk makro, enum anggota
    2. ThisIsMyConvention untuk nama file, nama objek (class, struct, enum, union ...), nama fungsi, nama metode, typedef
    3. this_is_my_convention variabel global dan lokal,
      parameter, struktur dan elemen gabungan
    4. thisismyconvention [opsional] variabel yang sangat lokal dan sementara (seperti indeks loop for ())

Dan itu dia.

Memberikan

class MyClass {
    enum TheEnumeration {
        FIRST_ELEMENT,
        SECOND_ELEMENT,
    }

    int class_variable;

    int MyMethod(int first_param, int second_parameter) {
        int local_variable;
        TheEnumeration local_enum;
        for(int myindex=0, myindex<class_variable, myindex++) {
             localEnum = FIRST_ELEMENT;
        }
    }
}
Luc Fourestier
sumber
8

Saya akan merekomendasikan untuk tidak mencampur case unta dan pemisahan garis bawah (seperti yang Anda usulkan untuk anggota struct). Ini membingungkan. Anda akan berpikir, hei saya punya get_lengthjadi saya mungkin harus melakukannya make_subsetdan kemudian Anda mengetahui itu sebenarnya makeSubset. Gunakan prinsip paling tidak heran, dan bersikaplah konsisten.

Saya menemukan CamelCase berguna untuk mengetik nama, seperti struct, typedefs dan enums. Itu tentang semuanya. Untuk yang lainnya (nama fungsi, nama anggota struct, dll.) Saya menggunakan underscore_separation.

Eli Bendersky
sumber
1
Ya, hal utama tentang konvensi penamaan apa pun adalah prediktabilitas dan konsistensi. Juga, karena pustaka C itu sendiri menggunakan semua huruf kecil dengan _ untuk jarak, saya akan merekomendasikan penggunaan itu hanya agar Anda tidak perlu berurusan dengan 2 konvensi penamaan yang berbeda dalam sebuah proyek (dengan asumsi Anda tidak menulis pembungkus di sekitar libc untuk membuatnya itu sesuai dengan penamaan Anda .. tapi itu kotor)
Earlz
Ia juga menggunakan typedefs dengan " t" di akhir, tapi saya tidak melihat ada yang merekomendasikan itu. Nyatanya, pustaka standar bahkan tidak konsisten: div_t (stdlib.h) adalah sebuah struct dan begitu juga dengan tm (time.h). Juga, lihat anggota struct tm, mereka semua diawali dengan tm yang tampaknya tidak berguna dan jelek (IMO).
JeffV
1
"Menurut saya CamelCase berguna untuk mengetik nama ..." Jika Anda memulainya dengan huruf besar, sebenarnya itu adalah PascalCase.
Tagc
7

Ini adalah yang (tampaknya) tidak umum, yang menurut saya berguna: nama modul di CamelCase, lalu garis bawah, lalu nama fungsi atau cakupan file di CamelCase. Jadi contohnya:

Bluetooth_Init()
CommsHub_Update()
Serial_TxBuffer[]
Steve Melnikoff
sumber
2
Tidak terlalu aneh, namun sangat berguna.
chux - Kembalikan Monica
3

Saya bingung dengan satu hal: Anda berencana membuat konvensi penamaan baru untuk proyek baru. Umumnya Anda harus memiliki konvensi penamaan yang berlaku di seluruh perusahaan atau tim. Jika Anda sudah memiliki proyek yang memiliki bentuk konvensi penamaan apa pun, Anda tidak boleh mengubah konvensi untuk proyek baru. Jika konvensi di atas hanyalah kodifikasi dari praktik Anda yang ada, maka Anda adalah emas. Semakin berbeda dari standar de facto yang ada, semakin sulit untuk mendapatkan mindshare dalam standar baru.

Tentang satu-satunya saran yang akan saya tambahkan adalah saya menyukai _t di akhir tipe dalam gaya uint32_t dan size_t. Ini sangat C-ish bagi saya meskipun beberapa mungkin mengeluh itu hanya "kebalikan" Hongaria.

jmucchiello.dll
sumber
3
Nah, konvensi di sini ada di semua tempat dan tidak konsisten, itulah sebabnya saya berangkat untuk mendokumentasikannya. Juga, itulah mengapa saya bertanya. Untuk melihat seperti apa konsensus komunitas.
JeffV
Saya mengerti rasa sakit itu. Tetapi pasti ada bagian dari konvensi Anda yang ada yang paling populer. Anda harus mulai dari sana dan bukan di halaman web Internet sembarangan. Anda juga harus bertanya kepada developer lain apa yang mereka anggap baik.
jmucchiello
7
Saya yakin nama jenis yang diakhiri dengan _t dicadangkan oleh standar POSIX.
kafe
4
Nama yang diakhiri dengan _t dicadangkan. Lihat gnu.org/software/libc/manual/html_node/Reserved-Names.html , "Nama yang diakhiri dengan '_t' dicadangkan untuk nama jenis tambahan."
Étienne
2

Anda juga harus memikirkan urutan kata-kata untuk melengkapi nama otomatis .

Praktik yang baik: nama perpustakaan + nama modul + tindakan + subjek

Jika suatu bagian tidak relevan, lewati saja, tetapi setidaknya nama modul dan tindakan harus selalu disajikan.

Contoh:

  • nama fungsi: os_task_set_prio, list_get_size,avg_get
  • define (di sini biasanya tidak ada bagian tindakan ):OS_TASK_PRIO_MAX
Gábor Kiss-Vámosi
sumber
0

Mungkin ada banyak, terutama IDE mendikte beberapa tren dan konvensi C ++ juga mendorong. Untuk C biasanya:

  • UNDERSCORED_UPPER_CASE (definisi makro, konstanta, anggota enumerasi)
  • underscored_lower_case (variabel, fungsi)
  • CamelCase (tipe khusus: struct, enums, unions)
  • uncappedCamelCase (oppa gaya Java)
  • UnderScored_CamelCase (variabel, fungsi di bawah jenis ruang nama)

Notasi Hungaria untuk global tidak masalah, tetapi tidak untuk tipe. Dan bahkan untuk nama yang sepele, harap gunakan setidaknya dua karakter.

renonsz
sumber
-1

Saya pikir itu bisa membantu untuk pemula: Konvensi penamaan variabel di c

  1. Anda harus menggunakan Karakter Abjad (az, AZ), Digit (0-9) dan Under Score (_). Ini tidak diperbolehkan untuk menggunakan Karakter khusus seperti:%, $, #, @ dll. Jadi, Anda dapat menggunakan user_name sebagai variabel tetapi tidak dapat menggunakan user & name .
  2. Tidak bisa menggunakan spasi antar kata. Jadi, Anda dapat menggunakan nama_pengguna atau nama pengguna atau nama pengguna sebagai variabel tetapi tidak dapat menggunakan nama pengguna .
  3. Tidak dapat memulai penamaan dengan digit. Jadi, Anda dapat menggunakan pengguna1 atau pengguna2 sebagai variabel tetapi tidak dapat menggunakan 1 pengguna .
  4. Ini adalah bahasa yang peka huruf besar kecil. Huruf besar dan huruf kecil penting. Jika Anda menggunakan variabel seperti username maka Anda tidak dapat menggunakan USERNAME atau Username untuk digunakan ayah.
  5. Anda tidak dapat menggunakan kata kunci apa pun (char, int, if, for, while dll) untuk deklarasi variabel.
  6. Standar ANSI mengenali panjang 31 karakter untuk nama variabel
Amranur Rahman
sumber
Posting ini jelas bertujuan untuk membahas konvensi penamaan , bukan batasan . Apa yang Anda daftarkan adalah hal-hal yang bahkan tidak dapat Anda lakukan karena itu adalah kesalahan sintaks.
Mengejar