Coding Standards for pure C (not C++)

前端 未结 11 1941
盖世英雄少女心
盖世英雄少女心 2020-12-12 14:17

I come from a java background (from my CS classes) and a semester of C++. I am just finishing up a OpenCV project for my Co-Op that\'s in pure C, so I\'m a bit late in aski

相关标签:
11条回答
  • 2020-12-12 15:05

    I honestly don't think that any number of answers on StackOverflow are going to teach you how to design and write well-structured C programs. You need to read a good book, and the obvious one to read is The C Programming Language by Kernighan & Ritchie.

    0 讨论(0)
  • 2020-12-12 15:11

    You may want to have a good look at the source of The Linux Kernel..... BTW it is not the easiest piece of code to start with but since you are from a programming background, it may help... As an object-oriented programmer, you might particularly find error-handling in C an uphill task. May be this helps---> http://www.freetype.org/david/reliable-c.html

    0 讨论(0)
  • 2020-12-12 15:12

    I have no professionnal experience on C (only on C++), so don't take my advices, tricks and tips too seriously, as they are "object-like-oriented".

    Almost Object C?

    Simulating basic object-like features can be done easily:

    In the header, forward declare your type, typedef it, and declare the "methods". For example:

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

    You'll see each functions is prefixed. I choose the name of the "struct" to make sure there won't be collision with another code.

    You'll see, too, that I used "p_pThis" to keep with the OO-like idea.

    In the source file, define your type, and define the functions:

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

    If you want "private" functions (or private global variables), declare them static in the C source. This way, they won't be visible outside:

    static void doSomethingPrivate()
    {
       /* etc. */
    }
    
    static int g_iMyPrivateCounter = 0 ;
    

    If you want inheritance, then you're almost screwed. If you believed everything in C was global, including variable, then you should get more experience in C before even trying to think how inheritance could be simulated.

    Misc. Tips

    Avoid multiple code-paths.

    For example, multiple returns is risky. For example:

    void doSomething(int i)
    {
       void * p = malloc(25) ;
    
       if(i > 0)
       {
          /* this will leak memory ! */
          return ;
       }
    
       free(p) ;
    }
    

    Avoid non-const globals

    This include "static" variables (which are not static functions).

    Global non-const variables are almost always a bad idea (i.e. see C API strtok for an example of crappy function), and if producing multithread safe code, they are a pain to handle.

    Avoid name collision

    Choose a "namespace" for your functions, and for your defines. This could be:

    #define GROOVY_LIB_x_MY_CONST_INT 42
    
    void GroovyLib_dosomething() ;
    

    Beware defines

    Defines can't be avoided in C, but they can have side effects!

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

    Initialize your variables

    Avoid declaring variables without initializing them:

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

    Uninitialized variables are causes of painful bugs.

    Know all the C API

    The C API function list as described in the K&R is quite small. You'll read the whole list in 20 minutes. You must know those functions.

    Wanna some experience?

    Rewrite the C API. For example, try to write your own version of the string.h functions, to see how it is done.

    0 讨论(0)
  • 2020-12-12 15:15

    You can restrict visibility of file-scope variables and functions to their respective source files (although that doesn't prevent you from passing pointers to these objects around).

    For example:

    /** 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 */
    
    0 讨论(0)
  • 2020-12-12 15:15

    Coding Style

    systemd

    systemd code quality tools

    RIOT-OS

    nginx

    Git Source Guidelines

    FFmpeg

    curl

    Architecture

    The Architecture of Open Source Applications C programs there include Git, Nginx, Open MPI, GPSD (C & Python), GDB, FreeRTOS, Berkeley DB, Bash, Asterisk,

    VLC (lots of architecture info)

    source examples

    Any of the above projects are worth a read. Standard command-line tools are also available to read. The Linux kernel has a lot of design documents out there too.

    0 讨论(0)
提交回复
热议问题