C'deki en yaygın adlandırma kuralları nelerdir?


126

C'de yaygın olarak kullanılan adlandırma kuralları nelerdir? En az iki tane olduğunu biliyorum:

  1. Küçük harfli_fonksiyonlu GNU / linux / K&R
  2. ? isim? UpperCaseFoo işlevleriyle

Sadece burada C'den bahsediyorum. Projelerimizin çoğu, C kullandığımız küçük gömülü sistemlerdir.

İşte bir sonraki projem için kullanmayı planladığım proje:


C Adlandırma Sözleşmesi

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)

7
Global değişkenler üzerinde bir 'g_' öneki zorlamazdım; Anlamlı isimleri zorlardım (yani client_locale ve cl_lc'yi global bir değişken adı olarak değil). Klasik C deve kılıfı kullanmaz; C de deve durumunda kod yazdım ve tuhaf görünüyor (bu yüzden artık böyle yapmıyorum). Bununla birlikte, bu yanlış değildir ve tutarlılık, hangi sözleşmenin kullanıldığından daha önemlidir. Yapı işaretçileri içeren yazı tiplerinden kaçının; C standardını düşünün - 'FILE *' bu şekilde yazılır, FILE_PTR değil.
Jonathan Leffler

2
@Jonathan Leffler, globalleri belirtmek için g_'nin nesi var? Gömülü sistemlerde, global değişkenler ve extern g_somevar aracılığıyla modüller arası bağımlılıkları takip etmenin zor olduğu daha önce sorunlar yaşadım. Şahsen bunun genellikle kötü bir fikir olduğunu düşünüyorum, ancak bu tür şeyler genellikle performans nedenleriyle yapılır. Örneğin, verilerin hazır olduğunu belirten bir kesme tarafından ayarlanan global bir bayrak.
JeffV

2
Ne olursa olsun, bu adlandırma kuralı çoğunlukla PalmOS API kurallarından koparıldı. Ayrıca, O'Reilly'nin "Gömülü Sistemleri C ve GNU Geliştirme Araçlarıyla Programlama" kitabında kullanılan konvansiyona benzer. Şahsen, işlev adlarında TitleCase'i seviyorum. İç bağlantı işlevlerinde lowerCamelCase ile gitmeyi düşünüyordum (soruma özel adını verdim).
JeffV

3
@Chris Lutz, yürekten katılıyorum. Mümkün olan her yerde değişkenler en dar kapsamda tutulmalıdır. Aslında tartıştığımız üç kapsam olduğuna dikkat edin: bir işleve yerel, bir modüle yerel (değişkene harici bağlantı yok) ve dış bağlantılı küreseller. Gömülü sistemlerde "globalden bir modüle" değişkenlerin olması yaygındır. Bu nedenle, minimumda tutulabilmeleri ve modül etkileşimlerinin anlaşılabilmesi için küreselleri dış bağlantı ile tanımlamaya özen gösterilmelidir. "G_" ön ekinin yararlı olduğu yer burasıdır.
JeffV

47
Global değişkenlerin önüne // koymayı seviyorum.
plafer

Yanıtlar:


129

Buradaki en önemli şey tutarlılıktır. Bununla birlikte, aşağıdaki gibi özetlenebilecek GTK + kodlama kuralını takip ediyorum:

  1. Tüm makrolar ve sabitler büyük harf: MAX_BUFFER_SIZE, TRACKING_ID_PREFIX.
  2. Camelcase'de Struct isimleri ve typedef'ler: GtkWidget, TrackingOrder.
  3. Yapılar üzerinde çalışan fonksiyonlar: klasik C stili: gtk_widget_show(), tracking_order_process().
  4. İşaretçiler: burada fantezi bir şey yok: GtkWidget *foo, TrackingOrder *bar.
  5. Global değişkenler: sadece global değişkenler kullanmayın. Onlar kötüler.
  6. Orada olan, ancak doğrudan çağrılmaması gereken veya belirsiz kullanımları olan işlevler veya her neyse: Başlangıçta bir veya daha fazla alt çizgi: _refrobnicate_data_tables(), _destroy_cache().

13
Altıncı noktada staticmodül önekini kullanmayı ve atlamayı tercih ederim , bu nedenle gtk_widget_show()dosya kapsamına sahip bir işlev olsaydı widget_show(), statik depolama sınıfı eklendiğinde basitçe olurdu .
Ağustos Karlstrom

27
6. nokta hakkında ek not: C standardı, _uygulama ve ileride kullanım için ile başlayan isimleri ayırma konusunda bazı kurallara sahiptir . İle başlayan isimlerin birkaç istisnası var _ama bence ezberlemeye değmez. Geçilmesi gereken güvenli bir kural _, kodunuzda ile başlayan isimleri asla kullanmamaktır . İlgili C SSS girişi: c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=decl#namespace
jw013

5
# 2 daha spesifik olarak üst deve kılıfı veya pascal durumdur . Deve harfleri veya küçük deve harfleri, ilk harfte küçük harf kullanır.
Clint Pachl

9
Yerel çok kelimeli değişkenler ne olacak? my_var veya myVar?
Dean Gurvitz

5
Global variables: just don't use global variables. They are evil.- gömülü proje üzerinde çalışmıyorsanız ve 1024 bayt RAM ve 8MHz CPU'nuz yoksa.
Kamil

30

"Struct işaretçileri", onları kapsayacak şekilde bir adlandırma kuralına ihtiyaç duyan varlıklar değildir. Onlar sadece struct WhatEver *. Zeki ve "bariz" bir typedef ile ilgili bir işaretçi olduğu gerçeğini SAKLAMAYIN. Hiçbir amaca hizmet etmez, artık yazmak içindir ve bildirim ile erişim arasındaki dengeyi bozar.


29
"İşaretçileri gizleme" yanıtı için +1 - bu yanıt sorunun geri kalanının çoğunu (henüz) ele almasa da.
Jonathan Leffler

1
@unwind, kabul etme eğilimindeyim. Bununla birlikte, bazen bir göstericinin dışarıdan referans gösterilmesi amaçlanmaz ve tüketici için kullanacakları bir yapının gerçek bir göstericisinden daha çok bir tutamaçtır. TitleCasePtr'den bunun için ayrıldım. typedef struct {alanlar} MyStruct, * MyStructPtr;
JeffV

TitleCasePtr'yi kaldırıyorum, asıl sorudan rahatsız ediyor.
JeffV

1
İşaretçi türü bildirimi, özellikle işlev imzalarında dağınıklığı azalttığından ve bildirim ile erişim arasındaki "dengesizlik" yalnızca uygulama dosyasında göründüğünden - istemci alan üyelerine doğrudan erişmez (olmamalıdır).
Ağustos Karlstrom

1
@AugustKarlstrom Güzel. Gerçi uygulama dosyasıyla ilgili bu kadar "sadece" neyin olduğunu anlamıyorum, o da kod değil mi? Soruyu sadece "dış" isimlerle ilgili olarak yorumlamadım. Tüm kod, bir düzeyde "uygulama" dır.
gevşeyin

17

Öncelikle C'nin genel / özel / sanal işlevleri yoktur. Bu C ++ 'dır ve farklı kuralları vardır. C'de tipik olarak şunlara sahip olursunuz:

  • ALL_CAPS içindeki sabitler
  • Yapılarda veya işlev adlarında sözcükleri sınırlandırmak için alt çizgiler, C'de neredeyse hiç deve durumu görmezsiniz;
  • yapılar, typedef'ler, sendikalar, üyeler (sendika ve yapıların) ve enum değerleri genellikle C ++ / Java / C # / etc ilk harfi büyük harf yapma kuralından ziyade küçük harflidir (benim deneyimlerime göre), ancak sanırım bu mümkün C de.

C ++ daha karmaşıktır. Burada gerçek bir karışım gördüm. Sınıf adları veya küçük harf + alt çizgi için deve durumu (deve durumu benim deneyimime göre daha yaygındır). Yapılar nadiren kullanılır (ve genellikle bir kitaplık gerektirdiği için, aksi takdirde sınıfları kullanırsınız).


@cletus, bunun farkındayım. Özel derken, modül başlığında harici olarak açığa çıkmayan ve modülün dışındaki kod tarafından kullanılması amaçlanmayan işlevleri kastediyorum. Genel, harici olarak kullanılması amaçlanan modül API işlevleri olacaktır.
JeffV

3
Statik işlevleri özel olarak kabul edebilirsiniz; soru sanaldan bahsetmiyor. Ancak 'nadiren C'de deve durumunu görürsünüz' için +1.
Jonathan Leffler

2
Jeff'in external linkage"genel işlevler" ve internal linkage"özel işlevler" anlamına geldiğini düşünüyorum .
pmg

1
KBufferSize'nin yanı sıra ak ile başlayan sabitleri gördüm. Bunun nereden geldiğinden emin değilim.
JeffV

2
ALL_CAPSgenellikle enum değerleri için de kullanılır.
15'te caf

15

Biliyor musun, basit ama açık tutmayı seviyorum ... İşte burada kullandığım şey, C:

  • Önemsiz Değişkenler : i,n,cvb ... (Yalnızca bir harf. Bir harf net değilse, Yerel Değişken yapın)
  • Yerel Değişkenler :lowerCamelCase
  • Global Değişkenler :g_lowerCamelCase
  • Sabit Değişkenler :ALL_CAPS
  • İşaretçi Değişkenleri : p_öneke bir ekleyin . Global değişkenler için gp_var, yerel değişkenler p_variçin, sabit değişkenler için olacaktır p_VAR. Uzak işaretçiler kullanılıyorsa, fp_yerine bir kullanın p_.
  • Yapılar : ModuleCamelCase(Modül = tam modül adı veya 2-3 harfli bir kısaltma, ancak yine de CamelCase.)
  • Struct Üye Değişkenleri :lowerCamelCase
  • Numaralandırmalar :ModuleCamelCase
  • Enum Değerleri :ALL_CAPS
  • Genel İşlevler :ModuleCamelCase
  • Özel İşlevler :CamelCase
  • Makrolar :CamelCase

Yapılarımı yazdım, ancak hem etiket hem de typedef için aynı adı kullanıyorum. Etiketin yaygın olarak kullanılması amaçlanmamıştır. Bunun yerine typedef'i kullanmak tercih edilir. Ayrıca typedef'i kapsülleme için genel modül başlığında bildiririm ve böylece typedef'd adını tanımda kullanabilirim.

Tam struct Örnek :

typdef struct TheName TheName;
struct TheName{
    int var;
    TheName *p_link;
};

Qt çerçevesi hakkında hiçbir şey bilmiyorum, ancak kodunuzu istediğiniz stil formatında yazabilirsiniz. Bildiğim kadarıyla hiçbir şey sizi bundan uzak tutmuyor.
SeanRamey

10

C #, java, C, C ++ ve aynı zamanda C hedefinde kodlama yaparak , hayatımı kolaylaştırmak için çok basit ve net bir adlandırma kuralı uyguladım.

Her şeyden önce, modern IDE'lerin (eclipse, Xcode ... gibi) gücüne dayanıyor, fareyle veya ctrl tıklama ile hızlı bilgi alma imkanı ... Bunu kabul ederek, herhangi bir önek, sonek kullanımını bastırdım. ve sadece IDE tarafından verilen diğer işaretler.

Ardından, kongre:

  • Her isim, sahip olduklarınızı açıklayan okunabilir bir cümle OLMALIDIR. "Bu benim sözleşmem" gibi.
  • Ardından, bir cümle içinden bir kongre çıkarmanın 4 yöntemi:
    1. Makrolar için THIS_IS_MY_CONVENTION , enum üyeleri
    2. ThisIsMyConvention dosya adı, nesne adı (sınıf, yapı, enum, birlik ...), fonksiyon adı, yöntem adı, typedef için
    3. this_is_my_convention global ve yerel değişkenler,
      parametreler, yapı ve birleşim öğeleri
    4. thisismyconvention [isteğe bağlı] çok yerel ve geçici değişkenler (for () döngü dizini gibi)

Ve bu kadar.

O verir

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;
        }
    }
}

8

Deve durumu ile alt çizgi ayrımını karıştırmamanızı tavsiye ederim (yapı üyeleri için önerdiğiniz gibi). Bu kafa karıştırıyor. Düşünürsünüz, hey var, get_lengthyani muhtemelen yapmalıyım make_subsetve sonra bunun aslında olduğunu anlarsınız makeSubset. En az şaşkınlık ilkesini kullanın ve tutarlı olun.

Yapı, typedef ve enums gibi isimleri yazmak için CamelCase'i yararlı buluyorum. Yine de hepsi bu kadar. Geri kalan her şey için (fonksiyon isimleri, struct üye isimleri vb.) Altçizgi_separation kullanıyorum.


1
Evet, herhangi bir adlandırma kuralıyla ilgili en önemli şey tahmin edilebilirlik ve tutarlılıktır. Ayrıca, C kitaplığının kendisi boşluk için _ ile tüm küçük harfleri kullandığından, bunu bir projede 2 farklı adlandırma kuralıyla uğraşmak zorunda kalmamanız için kullanmanızı tavsiye ederim (libc'nin etrafına yapmak için bir sarmalayıcı yazmadığınızı varsayarak) adınıza uygun .. ama bu iğrenç)
Earlz

Ayrıca , sonunda " t" olan typedef'ler kullanır , ancak bunu tavsiye eden kimseyi görmüyorum. Aslında, standart kitaplık bile tutarsızdır: div_t (stdlib.h) bir yapıdır ve tm (time.h) de öyle. Ayrıca, tm struct üyelerine bir göz atın, hepsinin önünde anlamsız ve çirkin görünen tm (IMO) bulunur.
JeffV

1
"CamelCase'i isimleri yazmak için yararlı buluyorum ..." Büyük harfle başlatırsanız, aslında PascalCase'dir.
Tagc

7

İşte faydalı bulduğum (görünüşe göre) nadir bir tanesi: CamelCase'deki modül adı, ardından bir alt çizgi, ardından CamelCase'de işlev veya dosya kapsamı adı. Yani mesela:

Bluetooth_Init()
CommsHub_Update()
Serial_TxBuffer[]

2
O kadar sıra dışı değil, ancak çok kullanışlı.
chux - Monica'yı eski durumuna getir

3

Bir şey kafam karıştı: Yeni bir proje için yeni bir adlandırma kuralı oluşturmayı planlıyorsunuz. Genelde şirket veya ekip çapında bir adlandırma kuralınız olmalıdır. Halihazırda herhangi bir adlandırma kuralı biçimine sahip projeleriniz varsa, yeni bir proje için kuralı değiştirmemelisiniz. Yukarıdaki sözleşme sadece mevcut uygulamalarınızın kodlanması ise, o zaman altındasınız. Mevcut fiili standartlardan ne kadar farklı olursa, yeni standartta fikir paylaşımı kazanmak o kadar zor olacaktır.

Ekleyeceğim tek öneri, uint32_t ve size_t tarzındaki türlerin sonunda _t'yi beğenmiş olmamdır. Bazıları "tersine" Macarca olduğundan şikayetçi olsa da, bu benim için çok C-ish.


3
Buradaki sözleşmeler her yerde ve tutarsız, bu yüzden bir tanesini belgelemek için yola çıkıyorum. Ayrıca bu yüzden soruyorum. Topluluk fikir birliğinin ne olduğunu görmek için.
JeffV

O acıyı anlıyorum. Ancak, en popüler olan mevcut sözleşmelerinizin bazı alt kümeleri olmalıdır. Oradan başlamalısınız, rastgele bir internet web sayfasında değil. Ayrıca diğer geliştiricilerinize neyin iyi olduğunu düşündüklerini sormalısınız.
jmucchiello

7
_T ile biten tür adlarının POSIX standardı tarafından ayrıldığına inanıyorum.
caf

4
_T ile biten isim ayrılmıştır. Bkz. Gnu.org/software/libc/manual/html_node/Reserved-Names.html , "'_t' ile biten adlar ek tür adları için ayrılmıştır."
Étienne

2

Ayrıca düşünmesi gereken kelimelerin sırayla yapmak için oto ismi tamamlamayı kolaylaştırır.

İyi bir uygulama: kitaplık adı + modül adı + işlem + konu

Bir bölüm ilgili değilse, atlayın, ancak en azından bir modül adı ve her zaman bir eylem sunulmalıdır.

Örnekler:

  • İşlev adı: os_task_set_prio, list_get_size,avg_get
  • tanımlayın (burada genellikle eylem bölümü yoktur ):OS_TASK_PRIO_MAX

0

Çok sayıda olabilir, özellikle IDE'ler bazı eğilimleri belirler ve C ++ kuralları da zorlayıcıdır. C için yaygın olarak:

  • UNDERSCORED_UPPER_CASE (makro tanımları, sabitler, sıralama üyeleri)
  • undercored_lower_case (değişkenler, işlevler)
  • CamelCase (özel türler: yapılar, numaralandırmalar, birlikler)
  • uncappedCamelCase (oppa Java stili)
  • UnderScored_CamelCase (değişkenler, ad alanı türlerinin altındaki işlevler)

Küreseller için Macar gösterimi iyidir, ancak türler için değildir. Ve önemsiz isimler için bile lütfen en az iki karakter kullanın.


-1

Bunların yeni başlayanlar için yardımcı olabileceğini düşünüyorum: c'deki değişkenlerin adlandırma kuralı

  1. Alfabetik Karakter (az, AZ), Rakam (0-9) ve Alt Skor (_) kullanmanız gerekir. %, $, #, @ Vb. Gibi özel bir Karakter kullanımına izin verilmez. Dolayısıyla, kullanıcı_adı değişkenini kullanabilir ancak kullanıcı & adı kullanamazsınız .
  2. Kelimeler arasında boşluk kullanılamaz. Dolayısıyla, kullanıcı_adı veya kullanıcı adı veya kullanıcı adını değişken olarak kullanabilirsiniz ancak kullanıcı adını kullanamazsınız .
  3. Rakamla isimlendirmeye başlanamaz. Dolayısıyla, değişken olarak user1 veya user2'yi kullanabilirsiniz ancak 1user kullanamazsınız .
  4. Büyük / küçük harfe duyarlı bir dildir. Büyük ve küçük harf önemlidir. Kullanıcı adı gibi bir değişken kullanıyorsanız , baba kullanımı için USERNAME veya Username kullanamazsınız.
  5. Değişken bildirimi için herhangi bir anahtar sözcük (char, int, if, for, while vb) kullanamazsınız .
  6. ANSI standardı, bir değişken adı için 31 karakterlik bir uzunluk tanır

Bu gönderi açıkça sınırlamaları değil adlandırma kurallarını tartışmayı amaçlamaktadır . Listeledikleriniz , sözdizimi hataları olduğu için yapamayacağınız şeylerdir .
Chase
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.