Codierungsstandards für reines C (nicht C++)

Lesezeit: 7 Minuten

wakenDeepBlues Benutzeravatar
Erwache DeepBlue

Ich habe einen Java-Hintergrund (aus meinen CS-Kursen) und ein Semester C++. Ich beende gerade ein OpenCV-Projekt für meine Co-Op, das in reinem C ist, also bin ich etwas spät dran, diese Frage zu stellen.

Was sind die Designprozesse und Codierungsstandards für reines C?

Ich bin vertraut mit objektorientierter Programmierung, Design und Best Practices. Ich bin nur ein bisschen ratlos bei einer nicht objektorientierten Sprache wie C. Jede einzelne Variable und Funktion scheint global zu sein. Es fühlt sich für mich wie ein echtes Durcheinander an.

  • Funktionen sind “global”, aber Variablen können unterschiedliche Geltungsbereiche haben …

    – Paercebal

    11. August 2009 um 19:47 Uhr

  • Funktionen können natürlich global oder dateistatisch sein

    anon

    11. August 2009 um 19:48 Uhr

  • @GMan, wenn genügend verschiedene Benutzer die Frage bearbeiten, wird sie von selbst zu CW. Ich habe meine CW-Stimme hinzugefügt…

    – bdonlan

    11. August 2009 um 19:51 Uhr

  • @bdonian Ein grober Missbrauch der Bearbeitungsfunktion, IMHO.

    anon

    11. August 2009 um 20:06 Uhr

Vielleicht interessieren Sie sich für die Antworten auf eine ähnliche Frage, die ich vor nicht allzu langer Zeit gestellt habe. Wenn Sie außerdem an C-Styleguides interessiert sind, sollten Sie einen Blick darauf werfen diese Seite da es ein Repository für C (und C++) Styleguides ist. Wenn Sie Lust auf a gut lachenwerfen Sie bitte einen Blick auf die NASA-C-Styleguide. Werfen Sie insbesondere einen Blick auf die fest Kommentar … Sie werden wissen, von wem ich spreche. Bitte keine Kommentare wie diese schreiben.

Ich persönlich empfehle die Styleguide für Indian Hill C mit einigen Modifikationen. Außerdem möchten Sie vielleicht das Buch kaufen C-Schnittstellen und Implementierungen wenn Sie Probleme haben, umfangreiche Programme in C zu entwerfen.

  • +1 wegen der Links zu Webseiten mit mehreren Links zu C-Standards.

    – Paercebal

    11. August 2009 um 21:30 Uhr

  • Leider ist der Link zu Indian Hill jetzt 404. Eine Google-Suche nach „indian hill c style guide pdf“ zeigt jedoch schnell eine Reihe möglicher Quellen. C- und C++-Styleguides scheint besonders nützlich, zumindest für Antiquare wie mich.

    – Jonathan Leffler

    5. April 2012 um 1:42 Uhr

  • Wenn Sie nach dem NASA C Style Guide suchen gut lachenversuchen Sie Seite 64!

    – Trient

    3. November 2020 um 1:48 Uhr

  • Der Link zum Indian Hill Guide funktioniert nicht. Ich habe es im Webarchiv gefunden, hier

    – sushant_padha

    12. Februar um 4:09 Uhr


Ich glaube ehrlich gesagt nicht, dass eine Reihe von Antworten auf StackOverflow Ihnen beibringen wird, wie man gut strukturierte C-Programme entwirft und schreibt. Sie müssen ein gutes Buch lesen, und das Offensichtliche zum Lesen ist Die Programmiersprache C von Kernighan & Ritchie.

  • Zu Designprozessen und Coding-Standards hat K&R nicht viel zu sagen. Es ist eine gute Einführung in C.

    – Romancierparty

    30. Juli 2019 um 19:36 Uhr

Benutzeravatar von paercebal
paercebal

Ich habe keine Berufserfahrung in C (nur in C++), also nehmt meine Ratschläge, Tricks und Tipps nicht zu ernst, da sie “objektorientiert” sind.

Fast Objekt C?

Die Simulation grundlegender objektähnlicher Merkmale kann einfach durchgeführt werden:

Deklarieren Sie im Header Ihren Typ vorwärts, geben Sie ihn ein und deklarieren Sie die “Methoden”. Zum Beispiel:

/* MyString.h */

#include <string.h>

/* Forward declaration */
struct StructMyString ;

/* Typedef of forward-declaration (note: Not possible in C++) */
typedef struct StructMyString MyString ;

MyString *       MyString_new() ;
MyString *       MyString_create(const char * p_pString) ;
void             MyString_delete(MyString * p_pThis) ;
size_t           MyString_length(const MyString * p_pThis) ;

MyString *       MyString_copy(MyString * p_pThis, const MyString * p_pSource) ;
MyString *       MyString_concat(MyString * p_pThis, const MyString * p_pSource) ;

const char *     MyString_get_c_string(const MyString * p_pThis) ;
MyString *       MyString_copy_c_string(MyString * p_pThis, const char * p_pSource) ;
MyString *       MyString_concat_c_string(MyString * p_pThis, const char * p_pSource) ;

Sie werden sehen, dass jeder Funktion ein Präfix vorangestellt ist. Ich wähle den Namen der “Struktur”, um sicherzustellen, dass es keine Kollision mit einem anderen Code gibt.

Sie werden auch sehen, dass ich “p_pThis” verwendet habe, um bei der OO-ähnlichen Idee zu bleiben.

Definieren Sie in der Quelldatei Ihren Typ und definieren Sie die Funktionen:

/* MyString.c */

#include "MyString.h"

#include <string.h>
#include <stdlib.h>

struct StructMyString
{
   char *      m_pString ;
   size_t      m_iSize ;
} ;

MyString * MyString_new()
{
   MyString * pMyString = malloc(sizeof(MyString)) ;

   pMyString->m_iSize = 0 ;
   pMyString->m_pString = malloc((pMyString->m_iSize + 1) * sizeof(char)) ;
   pMyString->m_pString[0] = 0 ;

   return pMyString ;
}

/* etc. */

Wenn Sie “private” Funktionen (oder private globale Variablen) wollen, deklarieren Sie sie in der C-Quelle als statisch. Auf diese Weise sind sie von außen nicht sichtbar:

static void doSomethingPrivate()
{
   /* etc. */
}

static int g_iMyPrivateCounter = 0 ;

Wenn Sie Erbschaft wollen, dann sind Sie fast am Arsch. Wenn Sie glaubten, alles in C sei global, einschließlich Variablen, dann sollten Sie mehr Erfahrung in C sammeln, bevor Sie überhaupt versuchen, darüber nachzudenken, wie Vererbung simuliert werden könnte.

Sonstiges Tipps

Vermeiden Sie mehrere Codepfade.

Beispielsweise ist eine mehrfache Rückgabe riskant. Zum Beispiel:

void doSomething(int i)
{
   void * p = malloc(25) ;

   if(i > 0)
   {
      /* this will leak memory ! */
      return ;
   }

   free(p) ;
}

Vermeiden Sie nicht-konstante Globale

Dazu gehören “statische” Variablen (die keine statischen Funktionen sind).

Globale nicht-konstante Variablen sind fast immer eine schlechte Idee (dh ein Beispiel für eine beschissene Funktion finden Sie unter C API strtok), und wenn Sie Multithread-sicheren Code produzieren, sind sie mühsam zu handhaben.

Vermeiden Sie Namenskollisionen

Wählen Sie einen “Namespace” für Ihre Funktionen und für Ihre Definitionen. Das könnte sein:

#define GROOVY_LIB_x_MY_CONST_INT 42

void GroovyLib_dosomething() ;

Vorsicht definiert

Defines können in C nicht vermieden werden, aber sie können Seiteneffekte haben!

#define MAX(a, b) (a > b) ? (a) : (b)

void doSomething()
{
   int i = 0, j = 1, k ;
   k = MAX(i, j) ;   /* now, k == 1, i == 0 and j == 1 */
   k = MAX(i, j++) ; /* now, k == 2, i == 0 and j == 3, NOT 2, and NOT 1 !!! */
}

Initialisieren Sie Ihre Variablen

Vermeiden Sie es, Variablen zu deklarieren, ohne sie zu initialisieren:

int i = 42 ; /* now i = 42 */
int j ;      /* now j can have any value */
double k ;   /* now f can have any value, including invalid ones ! */

Nicht initialisierte Variablen sind Ursachen für schmerzhafte Fehler.

Kennen Sie die gesamte C-API

Die im K&R beschriebene C-API-Funktionsliste ist ziemlich klein. Sie werden die ganze Liste in 20 Minuten lesen. Diese Funktionen müssen Sie kennen.

Willst du etwas Erfahrung?

Schreiben Sie die C-API neu. Versuchen Sie beispielsweise, Ihre eigene Version der string.h-Funktionen zu schreiben, um zu sehen, wie es gemacht wird.

  • Ich bin vorsichtig bei jeder Antwort, die mit “Ich habe keine Berufserfahrung in C” beginnt. Aber der Tipp ist ok. Erklären Sie vielleicht besser Ihre Perspektive und Argumentation, damit anderen klar ist, warum sie Ihrem Rat folgen sollten oder nicht.

    – Romancierparty

    30. Juli 2019 um 19:24 Uhr

  • “Vererbung” kann mithilfe der Strukturzusammensetzung etwas vorgetäuscht werden. MSVC wird dies problemlos handhaben. GCC erfordert möglicherweise die Verwendung der Option -fms-extensions.

    – Mike

    18. Januar 2021 um 3:29 Uhr

Sie können den Gültigkeitsbereich einer Funktion oder eines Objekts lokal für seine Quelldatei festlegen, indem Sie es als “statisch” deklarieren. Das hilft ein bisschen.

Ansonsten ist die typische Redewendung, die ich sehe, um Namespace-Konflikte zu vermeiden, eine Art Einrichtungskennung in den Namen einzufügen. Zum Beispiel könnte alles in foo.c foo_* heißen

Arbeiten Sie mit anderen guten C-Programmierern zusammen. Haben Sie eine Codeüberprüfung mit ihnen. Lassen Sie sie nicht nur Ihren Code sehen, sondern Sie sehen sich ihren Code an.

Benutzeravatar von KFro
KFr

Eine gute Nachricht ist, dass Sie in C halbobjektorientiert programmieren können. Sie können Daten schützen, Zugriffsfunktionen verfügbar machen usw. Es hat vielleicht nicht die ganze Raffinesse von C++, aber von dem, was ich von C++-Code anderer Leute gesehen habe , viele Leute nutzen die Fantasie sowieso nicht. Mit anderen Worten, die Leute schreiben C-Code innerhalb einer Klasse, wo Sie in C denselben Code ohne den Klassencontainer schreiben würden.

Lesen Sie zuerst ein Buch über C-Programmierung und -Stil, K&R ist in Ordnung. Zweitens würde ich das Auschecken empfehlen CERT-Programmierstandard. Auch wenn sich diese Seite hauptsächlich auf “sichere” Codierungsstandards konzentriert, handelt es sich bei einem Großteil des Inhalts hier um allgemeine Codequalitätsstandards, die jeder befolgen sollte. Wenn Sie die hier genannten Dinge tun, wird Ihre Qualität verbessert, lästige Fehler beseitigt und als Nebeneffekt Ihr Code sicherer.

Benutzeravatar von Gabriel Devillers
Gabriel Devillers

Vielleicht möchten Sie sich die Quelle des Linux-Kernels genau ansehen….. Übrigens ist es nicht das einfachste Stück Code, mit dem Sie beginnen können, aber da Sie einen Programmierhintergrund haben, kann es hilfreich sein … Als Objekt -orientierten Programmierern finden Sie möglicherweise insbesondere die Fehlerbehandlung in C eine schwierige Aufgabe. Vielleicht hilft das weiter—> http://www.freetype.org/david/reliable-c.html

1395620cookie-checkCodierungsstandards für reines C (nicht C++)

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

Privacy policy