Programming conventions

[ Why ? | File Names | Preprocessor Constants | Variable Names | Functions | from 32 to 64 bits ]


Why ?

Because certain coding conventions enhance readability of other person's program sources. Therefore a couple of coding conventions for the C language is suggested for software projects in biophysics.

File names

Use only lowercase file names.
One file should contain one function only, or at least only functions that belong logically together, e.g. functions to create, initialize and delete a particular data structure.

Preprocessor constants and macros

Preprocessor constants and macros should always be uppercase in order to distinguish them from program variables:
   #define MAXBRAGGPEAKS 10
   
It is also wise not to choose too simple names because they are likely to conflict with already defined ones. Also, one should include at least the name of the package for which they are defined, e.g.:
   #define TRP_BRAGGMAX 64 
   
is preferrable to just
   #define MAX 64 
   

Variable Names

Because there are a variety of basic data types in C it is good practice to choose the first character of a variable name in order to reflect the type ("hungarian notation"):
    long   lVar;
    int    iVar;
    float  rVar;
    double dVar;
    char   cVar;
    struct sVar { ... };

    long   *plVar;
    int    *piVar;
    float  *prVar;
    double *pdVar;
    char   *pcVar;
    struct sVar *psVar;
    void   *pvVar;
   
Never use 1-char variable names, e.g. i,j,k for loops. It is very hard to find them with automatic search procedures. Use e.g. ii, jj, kk instead.

Functions

Function entry point names should always reflect the package in which they are defined. This is because they are external entries and most likely subject to name conflicts.
For the same reason never use too simple names like "f1()", "add()", etc.
Also, functions should always provide at least an "int" return code indicating success or failure.
Functions should always be declared (prototyped) in some include file belonging to the package. This helps reducing nasty errors in the calling sequence because the compiler can check the parameter types.
Here is an example for a routine belonging to the TRiP package:
   ...
   #include "trp.h" 

   int TRPxyz( ... ) {
      int iRC = ERRTRP_SYS;    /* common error code */
      
      ...
      if ( ( pv = calloc(...) ) == NULL ) {  /* allocation failed */
         iRC = ERRTRP_SYS; goto gError; 
      }
      ...

      iRC = 0;
   gError:;
      return(iRC);
   }

   

from 32 to 64 bits

Current (as of 201x) CPUs offer the possibility to use a 64 bit address space and thus support RAM usage far beyond the classical 4GB limit. Current compilers support this feature on request, but this means that certain C (integer) data types have a larger size in 64bit mode than in 32bit mode. Obviously this affects software compatibility to a large extent.
Almost all compilers/OSs use the ILP=4/8/8 model, i.e. int stays at 4 bytes, long now uses 8 bytes, and pointers are also 8 bytes to allow for the 64bit address space. Floating point data/operations should not be affected, at least theoretically, since they should follow the IEEE standard. I've seen differences between 32 and 64 bit mode in numerical results, though, in particular on Linux/x86.
Some hints for making 32bit programs 64bit-ready:
Last Update: 3-Nov-2011, M.Kraemer