Was sind die gängigsten Namenskonventionen in C?

Lesezeit: 9 Minuten

Benutzeravatar von JeffV
JeffV

Welche Namenskonventionen werden üblicherweise in C verwendet? Ich weiß, es gibt mindestens zwei:

  1. GNU / Linux / K&R mit Kleinbuchstabenfunktionen
  2. ? Name ? mit UpperCaseFoo-Funktionen

Ich spreche hier nur von C. Die meisten unserer Projekte sind kleine eingebettete Systeme, in denen wir C verwenden.

Hier ist die, die ich für mein nächstes Projekt verwenden möchte:


C Namenskonvention

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)

  • Ich würde kein ‘g_’-Präfix für globale Variablen erzwingen; Ich würde aussagekräftige Namen erzwingen (also client_locale und nicht cl_lc als globaler Variablenname). Classic C verwendet kein Camel-Case; Ich habe Code in Camel-Case geschrieben, und es sieht komisch aus (also mache ich es nicht mehr so). Das heißt, es ist nicht falsch – und Konsistenz ist wichtiger als welche Konvention verwendet wird. Vermeiden Sie Typedefs, die Strukturzeiger kapseln; Beachten Sie den C-Standard – ‘FILE *’ wird so geschrieben, nicht FILE_PTR.

    – Jonathan Leffler

    12. November 2009 um 13:34 Uhr

  • @Jonathan Leffler, was ist falsch an g_, um Globals zu bezeichnen? In eingebetteten Systemen hatte ich zuvor Probleme, bei denen es schwierig war, Abhängigkeiten zwischen Modulen durch globale Vars und extern g_somevar aufzuspüren. Ich persönlich halte das im Allgemeinen für eine schlechte Idee, aber so etwas wird normalerweise aus Leistungsgründen durchgeführt. Zum Beispiel ein globales Flag, das durch einen Interrupt gesetzt wird und anzeigt, dass die Daten bereit sind.

    – JeffV

    12. November 2009 um 13:47 Uhr

  • Für das, was es wert ist, wurde diese Namenskonvention größtenteils von PalmOS-API-Konventionen gerissen. Außerdem ähnelt es der Konvention, die in O’Reillys Buch “Programming Embedded Systems with C and GNU Development Tools” verwendet wird. Mir persönlich gefällt der TitleCase in Funktionsnamen. Ich dachte daran, mit LowerCamelCase in internen Verknüpfungsfunktionen zu arbeiten (die ich in meiner Frage als privat bezeichnet habe).

    – JeffV

    12. November 2009 um 14:57 Uhr

  • @Chris Lutz, dem stimme ich von ganzem Herzen zu. Wo immer möglich, sind Variablen im engsten Geltungsbereich zu halten. Beachten Sie, dass es eigentlich drei Bereiche gibt, die wir besprechen: lokal für eine Funktion, lokal für ein Modul (keine externe Verknüpfung mit der Variablen) und die globalen mit externer Verknüpfung. Es ist üblich, in eingebetteten Systemen “global für ein Modul”-Variablen zu haben. Daher muss darauf geachtet werden, die Globals mit externer Verknüpfung zu identifizieren, damit sie auf einem Minimum gehalten und die Modulinteraktionen verstanden werden können. Hier ist das Präfix “g_” hilfreich.

    – JeffV

    13. November 2009 um 0:23 Uhr

  • Ich stelle globalen Variablen gerne // voran.

    – Teller

    24. November 2015 um 5:26 Uhr

Das Wichtigste hier ist die Konsistenz. Allerdings folge ich der GTK+-Codierungskonvention, die wie folgt zusammengefasst werden kann:

  1. Alle Makros und Konstanten in Großbuchstaben: MAX_BUFFER_SIZE, TRACKING_ID_PREFIX.
  2. Strukturnamen und Typedefs in Camelcase: GtkWidget, TrackingOrder.
  3. Funktionen, die mit Strukturen arbeiten: klassischer C-Stil: gtk_widget_show(), tracking_order_process().
  4. Hinweise: nichts Besonderes hier:
    GtkWidget *foo, TrackingOrder *bar.
  5. Globale Variablen: Verwenden Sie einfach keine globalen Variablen. Sie sind böse.
  6. Funktionen, die vorhanden sind, aber nicht direkt aufgerufen werden sollten oder obskure Verwendungen haben oder was auch immer: ein oder mehrere Unterstriche am Anfang:
    _refrobnicate_data_tables(), _destroy_cache().

  • In Punkt sechs verwende ich lieber static und überspringen Sie das Modulpräfix, also if gtk_widget_show() war eine Funktion mit Dateibereich, würde es einfach werden widget_show() mit statischer Speicherklasse hinzugefügt.

    – August Karlström

    15. August 2013 um 14:28 Uhr

  • Zusätzliche Anmerkung zu Punkt 6: Der C-Standard hat einige Regeln für die Reservierung von Namen, die mit beginnen _ für die Implementierung und zukünftige Verwendung. Es gibt einige Ausnahmen von Namen, die mit beginnen _ aber meiner Meinung nach lohnt es sich nicht, es auswendig zu lernen. Eine sichere Regel ist, niemals Namen zu verwenden, die mit beginnen _ in deinem Code. Relevanter C-FAQ-Eintrag: c-faq.com/~scs/cgi-bin/faqcat.cgi?sec=decl#namespace

    – jw013

    21. März 2014 um 21:08 Uhr

  • #2 ist genauer oberes Kamelgehäuse oder Pascal-Fall. Camel Case oder Lower Camel Case verwendet Kleinbuchstaben für den ersten Buchstaben.

    – Clint Pachl

    1. November 2017 um 5:44 Uhr

  • Was ist mit lokalen Mehrwortvariablen? meine_var oder meineVar?

    – Dekan Gurvitz

    9. August 2018 um 7:24 Uhr

  • Global variables: just don't use global variables. They are evil. – es sei denn, Sie arbeiten an einem eingebetteten Projekt und haben 1024 Bytes RAM und eine 8-MHz-CPU.

    – Kamil

    23. April 2019 um 15:38 Uhr

“Strukturzeiger” sind keine Entitäten, die eine Namenskonventionsklausel benötigen, um sie abzudecken. Sie sind einfach struct WhatEver *. Verbergen Sie NICHT die Tatsache, dass ein Zeiger mit einer cleveren und “offensichtlichen” Typdefinition involviert ist. Es erfüllt keinen Zweck, ist länger zu tippen und zerstört die Balance zwischen Deklaration und Zugriff.

  • +1 für das Zeug “Zeiger nicht ausblenden” – obwohl diese Antwort (noch) nicht viel vom Rest der Frage anspricht.

    – Jonathan Leffler

    12. November 2009 um 13:35 Uhr

  • @unwind, da stimme ich eher zu. Manchmal soll ein Zeiger jedoch nicht extern dereferenziert werden und ist eher ein Handle für den Verbraucher als ein tatsächlicher Zeiger auf eine Struktur, die er verwenden wird. Dafür habe ich den TitleCasePtr verlassen. typedef struct {Felder} MyStruct, *MyStructPtr;

    – JeffV

    12. November 2009 um 13:35 Uhr

  • Ich entferne den TitleCasePtr, er lenkt von der eigentlichen Frage ab.

    – JeffV

    12. November 2009 um 13:40 Uhr

  • -1 von mir, da eine Deklaration des Zeigertyps Unordnung reduziert, insbesondere in Funktionssignaturen, und das “Ungleichgewicht” zwischen Deklaration und Zugriff nur in der Implementierungsdatei auftaucht – der Client greift (sollte) nicht direkt auf die Feldmitglieder zu.

    – August Karlström

    15. August 2013 um 14:47 Uhr

  • @AugustKarlstrom Gut. Ich verstehe nicht, was so “nur” an der Implementierungsdatei ist, ist das nicht auch Code? Ich habe die Frage nicht nur als “externe” Namen interpretiert. Der gesamte Code ist auf einer bestimmten Ebene “Implementierung”.

    – abschalten

    15. August 2013 um 14:59 Uhr

Benutzeravatar von SeanRamey
SeanRamey

Weißt du, ich halte es gerne einfach, aber klar … Also hier ist, was ich in C verwende:

  • Triviale Variablen: i,n,cetc … (Nur ein Buchstabe. Wenn ein Buchstabe nicht klar ist, dann machen Sie ihn zu einer lokalen Variablen)
  • Lokale Variablen: camelCase
  • Globale Variablen: g_camelCase
  • Konstante Variablen: ALL_CAPS
  • Zeigervariablen: füge hinzu ein p_ zum Präfix. Für globale Variablen wäre es gp_varfür lokale Variablen p_varfür konstante Variablen p_VAR. Wenn far-Zeiger verwendet werden, verwenden Sie an fp_ Anstatt von p_.
  • Strukturen: ModulePascalCase (Modul = vollständiger Modulname oder eine Abkürzung aus 2-3 Buchstaben, aber immer noch in PascalCase.)
  • Strukturmitgliedsvariablen: camelCase
  • Aufzählungen: ModulePascalCase
  • Enum-Werte: ALL_CAPS
  • Öffentliche Funktionen: ModulePascalCase
  • Private Funktionen: PascalCase
  • Makros: PascalCase

Ich typdefiniere meine Strukturen, verwende aber denselben Namen für das Tag und die Typdefinition. Das Tag soll nicht allgemein verwendet werden. Stattdessen ist es vorzuziehen, die typedef zu verwenden. Ich deklariere auch die Typedef im Header des öffentlichen Moduls für die Kapselung und damit ich den Typedef-Namen in der Definition verwenden kann.

Voll struct Beispiel:

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

  • Ich weiß nichts über das qt-Framework, aber Sie können Ihren Code in jedem gewünschten Stilformat schreiben. Nichts hält dich davon ab, soweit ich weiß.

    – SeanRamey

    12. August 2018 um 1:11 Uhr

  • Ist es nicht PascalCase und camelCase?

    – Michael

    20. Oktober 2020 um 12:50 Uhr

  • Dieses Format ähnelt den Namenskonventionen von Java und c#. Ich würde Ihnen einfach vorschlagen, camelCase für die Benennung von Funktionen und ein Modulpräfix dafür zu verwenden, z MDL_functionName() und ich sehe auch keinen Vorteil darin, p_-Präfix für die Zeiger zu verwenden, ich würde es auch entfernen.

    – Osmann

    11. April um 9:47 Uhr


Nun, erstens hat C keine öffentlichen/privaten/virtuellen Funktionen. Das ist C++ und es hat andere Konventionen. In C haben Sie normalerweise:

  • Konstanten in ALL_CAPS
  • Unterstriche zum Trennen von Wörtern in Strukturen oder Funktionsnamen, kaum jemals sieht man Camel Case in C;
  • Structs, Typedefs, Unions, Members (von Unions und Structs) und Enum-Werte sind normalerweise in Kleinbuchstaben (meiner Erfahrung nach) und nicht in der C++/Java/C#/etc-Konvention, den ersten Buchstaben groß zu schreiben, aber ich denke, es ist möglich in C auch.

C++ ist komplexer. Ich habe hier eine echte Mischung gesehen. Camel-Case für Klassennamen oder Kleinbuchstaben + Unterstriche (Camel-Case ist meiner Erfahrung nach häufiger). Strukturen werden selten verwendet (und normalerweise, weil eine Bibliothek sie benötigt, sonst würden Sie Klassen verwenden).

Benutzeravatar von Luc Fourestier
Luc Fourestier

Codierung ein C#, Java, C, C++ und objektives C Gleichzeitig habe ich eine sehr einfache und klare Namenskonvention angenommen, um mein Leben zu vereinfachen.

Zuallererst stützt es sich auf die Leistungsfähigkeit moderner IDEs (wie Eclipse, Xcode …), mit der Möglichkeit, schnelle Informationen durch Bewegen der Maus oder Strg-Klick zu erhalten … In Anbetracht dessen habe ich die Verwendung von Präfixen und Suffixen unterdrückt und andere Markierungen, die einfach von der IDE gegeben werden.

Dann die Konvention:

  • Alle Namen MÜSSEN ein lesbarer Satz sein, der erklärt, was Sie haben. Wie “das ist meine Konvention”.
  • Dann 4 Methoden, um eine Konvention aus einem Satz zu bekommen:
    1. THIS_IS_MY_CONVENTION für Makros Aufzählungsmitglieder
    2. Das ist meine Konvention für Dateiname, Objektname (class, struct, enum, union…), Funktionsname, Methodenname, typedef
    3. das_ist_meine_Konvention globale und lokale Variablen,
      Parameter, Struct- und Union-Elemente
    4. thisismyconvention [optional] sehr lokale und temporäre Variablen (wie ein for() Schleifenindex)

Und das ist es.

Es gibt

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

Benutzeravatar von Steve Melnikoff
Steve Melnikoff

Hier ist ein (anscheinend) ungewöhnlicher, den ich nützlich fand: Modulname in CamelCase, dann ein Unterstrich, dann Funktions- oder Dateibereichsname in CamelCase. Also zum Beispiel:

Bluetooth_Init()
CommsHub_Update()
Serial_TxBuffer[]

Benutzeravatar von Eli Bendersky
Eli Bendersky

Ich würde davon abraten, Camel Case und Underscore-Trennung zu mischen (wie Sie es für Strukturmitglieder vorgeschlagen haben). Das ist verwirrend. Sie würden denken, he ich habe get_length also hätte ich es wohl haben sollen make_subset und dann findest du heraus, dass es tatsächlich so ist makeSubset. Verwenden Sie das Prinzip des geringsten Erstaunens und bleiben Sie konsequent.

Ich finde CamelCase nützlich, um Namen wie Strukturen, Typedefs und Enums einzugeben. Das ist aber auch schon alles. Für den Rest (Funktionsnamen, Strukturelementnamen usw.) verwende ich underscore_separation.

  • Ja, die Hauptsache bei jeder Namenskonvention ist Vorhersagbarkeit und Konsistenz. Da die C-Bibliothek selbst nur Kleinbuchstaben mit _ für Leerzeichen verwendet, würde ich empfehlen, dies zu verwenden, damit Sie sich nicht mit zwei verschiedenen Namenskonventionen in einem Projekt befassen müssen (vorausgesetzt, Sie schreiben keinen Wrapper um libc zu machen es entspricht Ihrer Benennung.. aber das ist ekelhaft)

    – Earlz

    12. November 2009 um 14:14 Uhr

  • Es verwendet auch Typedefs mit einem “t” am Ende, aber ich sehe niemanden, der das empfiehlt. Tatsächlich ist die Standardbibliothek sogar inkonsistent: div_t (stdlib.h) ist eine Struktur und ebenso tm (time.h). Schauen Sie sich auch um Bei den tm-Strukturmitgliedern ist ihnen allen das Präfix tm vorangestellt was sinnlos und hässlich erscheint (IMO).

    – JeffV

    12. November 2009 um 14:27 Uhr

  • “Ich finde CamelCase nützlich, um Namen einzugeben …” Wenn Sie es mit Großbuchstaben beginnen, ist es eigentlich PascalCase.

    – Tagc

    15. Dezember 2016 um 13:37 Uhr

1425360cookie-checkWas sind die gängigsten Namenskonventionen in C?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy