web-dev-qa-db-fra.com

Normes de codage pour PURE C (NOT C ++)

Je viens d'un Java Contexte (de mes classes CS) et un semestre de C++. Je suis juste terminé un projet OpenCV pour ma coopérative qui est en pure C, donc je suis un peu tard pour poser cette question.

Quels sont les processus de conception et les normes de codage pour pure C?

Je connais la programmation, la conception et les meilleures pratiques orientées objet. Je suis un peu à une perte dans une langue non orientée objet comme C. Chaque variable et chaque fonction semble être globale. Cela me fait sentir comme un vrai gâchis pour moi.

34
awakenDeepBlue

Vous êtes peut-être intéressé à consulter les réponses à une question similaire que j'ai demandé il n'y a pas trop longtemps. De plus, si vous êtes intéressé par des guides de style C, vous voudrez peut-être jeter un coup d'œil à cette page car il s'agit d'un référentiel pour les guides de style C (et C++). Si vous êtes d'humeur pour un Bon rire , veuillez consulter le Guide de style NASA C . En particulier, jetez un coup d'oeil au Massive Commentaire ... vous saurez de savoir dont je parle. N'écrivez pas de commentaires comme ça s'il vous plaît.

Je recommande personnellement le Guide de style de la colline indienne avec quelques modifications. En outre, vous voudrez peut-être acheter le livre interfaces et implémentations Si vous avez du mal à concevoir des programmes à grande échelle dans C.

31
anon

Honnêtement, je ne pense pas que tout nombre de réponses sur Stackoverflow va vous apprendre à concevoir et à écrire des programmes C bien structurés. Vous devez lire un bon livre et l'évident à lire est le langage de programmation C de Kernighan & Ritchie.

15
anon

Je n'ai aucune expérience sur C professionnel (uniquement sur C++), alors ne prenez pas mes conseils, trucs et astuces trop au sérieux, car ils sont " orientés objet comme- ".

Presque objet C?

Fonctionnalités de base-simulant comme objet peut se faire facilement:

Dans l'en-tête, déclarer avant votre type, typedef, et déclarer les " méthodes ". Par exemple:

/* 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) ;

Vous verrez chaque fonction est préfixé. Je choisis le nom du " struct " pour vous assurer qu'il n'y aura pas de collision avec un autre code.

Vous verrez aussi que je " p_pThis " pour maintenir le OO comme idée.

Dans le fichier source, définir votre type et définir les fonctions:

/* 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. */

Si vous voulez que les fonctions " privées " (ou variables globales privées), les déclarer statique dans la source C. De cette façon, ils ne seront pas visibles à l'extérieur:

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

static int g_iMyPrivateCounter = 0 ;

Si vous voulez l'héritage, alors vous êtes presque foutus. Si vous croyiez tout en C était globale, y compris la variable, alors vous devriez obtenir plus d'expérience en C avant même d'essayer de penser comment pourrait simuler l'héritage.

Misc. Des astuces

Évitez plusieurs chemins de code.

Par exemple, plusieurs retours est risqué. Par exemple:

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

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

   free(p) ;
}

Évitez non const GLOBALS

Cela inclut les variables " statiques " (qui ne sont pas des fonctions statiques).

Les variables globales non-const sont presque toujours une mauvaise idée (par exemple voir C API strtok pour un exemple de fonction merdique), et si la production du code multithread sûr, ils sont une douleur à la poignée.

Éviter la collision de nom

Choisissez un " espace de noms " pour vos fonctions et vos définit. Cela pourrait être:

#define GROOVY_LIB_x_MY_CONST_INT 42

void GroovyLib_dosomething() ;

Méfiez-vous définit

Définit ne peuvent pas être évités en C, mais ils peuvent avoir des effets secondaires!

#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 !!! */
}

Initialiser vos variables

Évitez la déclaration des variables sans les initialiser:

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 ! */

Les variables non initialisées sont des causes de bugs douloureuses.

Connaître toutes les API C

La liste des fonctions de l'API C comme décrit dans le K & R est assez faible. Vous allez lire la liste complète en 20 minutes. Vous devez connaître ces fonctions.

Vous voulez un peu d'expérience?

Réécrire l'API C. Par exemple, essayez d'écrire votre propre version des fonctions de string.h, pour voir comment il est fait.

9
paercebal

Vous pouvez faire une lunette locale de fonction ou d'objet à son fichier source en la déclarant "statique". Cela aide un peu.

Sinon, l'idiome typique que je vois pour éviter les affrontements d'espace de noms est de mettre une sorte d'identifiant de l'installation sur le nom. Par exemple, tout dans FOO.C pourrait être nommé foo_ *

8
T.E.D.

Travaillez avec d'autres programmes C Programmeurs C. Avoir un code de code avec eux. Non seulement les laisser regarder votre code, mais vous regardez leur code.

4
Robert

Les bonnes nouvelles sont que vous pouvez programmer de manière orientée semi-objet dans C. Vous pouvez protéger les données, exposer les fonctions d'accès, etc. Il peut ne pas avoir toute la fantaisie de C++, mais de ce que j'ai vu du code C++ d'autres personnes. De toute façon, beaucoup de gens n'utilisent pas la fantaisie de toute façon. En d'autres termes, les gens écrivent C code C dans une classe, où vous écrivez dans C, vous écrivez le même code sans le conteneur de classe.

Tout d'abord, lisez un livre sur la programmation et le style C, K & R est bien. Deuxièmement, je recommanderais de vérifier Standard de programmation CERT . Même si ce site est principalement axé sur les normes de codage "sécurisées", une grande partie du contenu est une grande partie des normes de qualité générales que tout le monde devrait suivre. Faire les choses mentionnées ici amélioreront votre qualité, éliminera les bugs pesky et comme effet secondaire, rendez votre code plus sécurisé.

3
KFro

Vous voudrez peut-être avoir un bon coup d'œil à la source du noyau Linux ..... BTW Ce n'est pas le code de code le plus facile de commencer, mais que vous êtes depuis une programmation, cela peut vous aider ... comme objet -Les programmeursOrientés, vous pourriez particulièrement trouver une manipulation erronée dans C une tâche de montée. Peut-être cela aide ---> - http://www.freetype.org/david/reliable-c.html

2
puffadder

Vous pouvez faire des conceptions orientées objet dans Pure C. Une approche facile consiste à penser à un module en tant que class avec des méthodes publiques comme des fonctions ordinaires nécessitant le paramètre this comme premier argument explicite.

Il aide si le nom class est un préfixe sur le nom de la fonction, et si toutes les fonctions privées et les données de classe sont déclarées static. Vous construisez des constructeurs avec malloc() pour obtenir la mémoire et une initialisation explicite des champs de données.

Un constructeur pour un objet avec des membres de données entièrement privés peut exposer un pointeur opaque (dactylographié void * Même, ou comme un pointeur à un type incomplet si la sécurité est souhaitée). Si vous souhaitez avoir uniquement des membres de données publiques, un pointeur sur un struct fonctionne bien.

Ce modèle est suivi d'un certain nombre de bibliothèques. Une fonction d'initialisation renvoie un cookie qui doit être transmis à toutes les méthodes de la bibliothèque et une méthode sert de destructeur.

Bien sûr, il existe d'autres moyens de concevoir bien dans Pure C, mais si OO fonctionne pour vous, vous n'avez pas à l'abandonner complètement.

1
RBerteig

Vous pouvez restreindre la visibilité des variables de périmètre de fichiers et des fonctions à leurs fichiers source respectifs (bien que cela ne vous empêche pas de passer des pointeurs à ces objets).

Par exemple:

/** foo.c */
static void foo_helper() {...} /* foo_helper cannot be called by name 
                                  outside of foo.c */
static int local_state;        /* local state is visible at file scope,
                                  but is not exported to the linker */
1
John Bode

Style de codage

Systemd

Outils de qualité du code SystemD

Riot-OS

nginx

Git Source Guidelines

FFMPEG

CURL

Architecture

l'architecture d'applications open source C Programmes Inclure Git, Nginx, Open MPI, GPSD (C & Python), GDB, Freertos, Berkeley DB, Bash, Asterisk,

VLC (beaucoup d'informations d'architecture

exemples source

N'importe lequel des projets ci-dessus valent la peine de lire. Des outils de ligne de commande standard sont également disponibles pour lire. Le noyau Linux a également beaucoup de documents de conception.

0
novelistparty

Si vous êtes intéressé par des normes d'environnement critiques, Misra C pourrait vous intéresser. J'ai trouvé ça utile.

Vous pouvez obtenir MISRA C 2004 ici .

Aperçu court de la MISRA MISE MISE MAJ 2012 ICI .

0
Michal M.