Layout

  • General Regulations
  • Expressions
  • Control Structures
  • Record Type
  • Class
  • Prechecked Loop
  • Postchecked Loop
  • Counting Loop
  • Binary Selection
  • Selection
  • Functions
  • Function Declaration
  • Function Definition
  • Function Call
  • Types And Instances
  • Modules
  • Comments

  • General Regulations

    1. Each line of code contains one expression at most.
    2. Lines should not exceed a length of 80 characters. Expressions may be wrapped to multiple lines, if necessary. The succeeding lines are indented by one level.
      1. nCounter =
            10 * StartOfRange() * OFFSET - SafeDistance();

    3. The tab width is 4 characters. The tab width is to declare in the file header.
    4. The indentation width is one tab (4 characters respectively, if different from tab width).
    5. A comma or semicolon is never preceeded by a whitespace (blank, tab, newline).
    6. A comma or semicolon is always followed by a whitespace (blank, tab, newline).
    7. Single source files exceed the length of 1,500 lines only by way of exception.
    8. Comment templates are used for file and function headers.

    Expressions

    1. If an expression in brackets has to be splitted to more than one line, (e.g. a long if-condition or a function's parameter list), the outer brackets are placed in the same column and are indented by one level to avoid confusion with curly braces. The expression itself is indented by an additional level.
      1. if
            (
                ((MIN_RANGE < nCounter) && (MAX_RANGE > nCounter)) ||
                (0 == nCounter)
            )
        {
            Expressions();
        }

        memcpy
            (
                pDestination,
                pSource,
                lSize
            );

    2. Operators are enclosed within whitespace characters.
    3. Exception: the operators dereferenciation and Address are placed directly at the name they are applied to, without any whitespace. If they are applied to an expression, the expression must be enclosed by parentheses.

      C/C++

      Pascal/Delphi

      int i = 27 * *pSum;
      y = f(17 + &x);
      float x = *(pBuffer->m_pData);
      i := 27 * pSum^;
      y := f(17 + @x);
      x := (pBuffer^.m_pData)^;
    4. In a pointer or reference declaration the operator is written directly to the type. A typedef declaration is preferred.
        1. double* pSum;
          float Function(const CComplex& anApproach);

        better:

      C/C++

      Pascal/Delphi

      typedef double* PDOUBLE;
      PDOUBLE pMean, pVariance;
      type PDOUBLE = ^double;
      var pMean, pVariance: PDOUBLE;
    5. Parentheses are neither preceeded nor followed by whitespaces, except parentheses led or followed by an operator or key word respectively.
        1. f(c), Pi() + 13, if (bCondition),

        but not:

          f (c), f( c ), Pi()+13

    6. In a comparison the constant should be placed left to the operator to avoid an accidental assignment.
      1. if (NULL == pDataBuffer)
        {
            return;
        }

    7. Type casts have always the form
      1. LONG(nNumber) * Size(); // C++

      or

        (LONG)(nNumber) * Size(); /* C */

      and not

        (LONG) nNumber * Size();

      to make the cast's range clear.

    8. (C, C++) The ? operator is to use sparingly. In doubt, prefer an if-else construct. A ? expression must not be split to multiple lines (in this case an if-else construct is mandatory). If a component of an ?: expression is an expression itself, it must be enclosed within brackets.
      1. nLength = (NULL != p) ? ::strlen(p) : 0;
            // ::strlen() parameter must not be NULL.

    Control Structures

    1. The block-enclosing curly braces have the same indentation level as the statements before and after the block.
      1. C/C++

        Pascal/Delphi

        Statements();

        for (i = 0; LIMIT > i; ++i)
        {
            Statements();
        }

        Statements();

        Statements;

        for i := 0 to Pred(LIMIT) do
        begin
            Statements;
        end {for};

        Statements;

    2. Before (key word) and after (closing brace) a control structure an empty line is inserted (optional before an else), except there is only an opening brace in the preceeding line. Control structures are formmatted as follows:
    3. control structure

      C/C++

      Pascal/Delphi

      record

      typedef struct
      {
          float m_fReal;
          float m_fImag;
      } CComplex;
      type CComplex =
      record
          m_fReal: single;
          m_fImag: single;
      end {record};

      class

      class C : CSuperclass
      {
          public:
              C(void);

          private:
              int m_nSize;
      };

      type C =
      class (CSuperclass)
          public
              constructor Create;

          private
              m_nSize: integer;
      end {class};

      prechecked loop

      while (bExpression)
      {
          Statements();
      }
      while (bExpression) do
      begin
          Statements;
      end {while};

      postchecked loop

      do
      {
          Statements();
      } while (bExpression);
      repeat
          Statements;
      until (not bExpression);

      counting loop

      for (i = 0; i < MAXIMUM; ++i)
      {
          Statements();
      }
      for i := 0 to Pred(MAXIMUM) do
      begin
          Statements;
      end {for};

      binary selection

      if (bExpression)
      {
          Statements();
      }

      else if (bExpression)
      {
          Statements();
      }

      else
      {
          Statements();
      }

      if (bExpression) then
      begin
          Statements;
      end

      else if (bExpression) then
      begin
          Statements;
      end

      else
      begin
          Statements;
      end {if};

      selection

      switch (nChoice)
      {
          case 1:
          {
              Statements();
              break;
          }

          default:
          {
              Statements();
              break;
          }
      }

      case (nChoice) of
          1:
          begin
              Statements;
          end;

          else
          begin
              Statements;
          end;
      end {case};

      (C, C++) Case labels in a switch statement may be combined (i.e. there is no code between two case labels). This is to point out in a comment before the label group. If the break statement is missing between two case labels (i.e. there is code between the labels), an ample comment has to point out this situation and must mention the following label!

        switch (nNumber)
        {
            case 1:
            {
                int n = 0;
                Statements();
                break;
            }

            // case group: explanation of the common characteristics
            case 2:
            case 3:
            case 4:
            {
                Statements();
                break;
            }

            case 5:
            {
                Statements();
                //-- No break; continue with 6 --//
            }

            case 6:
            {
                Statements();
                break;
            }
        }

      (C) Switch statements may be formatted by indenting the case labels half a level, if, for effinciency purposes, function calls would be too expensive and several control structures have therefore to be nested.

        switch (nChoice)
        {
          case 1:
          {
            Statements();
            break;
          }

          default:
          {
            Statements();
            break;
          }
        }

    4. The block of a control structure must always be enclosed within braces (except cases within a switch statement), even if it is empty.
      1. while (!DidTimerExpire())
        {
        }

    5. A control structure's condition is never placed on the same line with its statement.
    6. while (bCondition)
      {
          Statements();
      }

      while (Condition())
      {
      }

      Inadmissible: while (bCondition) Statement();
      while (bCondition);

    Functions

    Function Declaration

    1. In a function declaration the parameters are either declared in a single line or each parameter is declared on a seperate line. (C) Function declarations using K&R syntax are forbidden.

      C/C++

      int Sum(const int n1, const int n2, float f);

      void PushCommand
          (
              PStack pCommandStack,
              const CCommand aCommand
          );

      Pascal/Delphi

      function Sum(const n1, n2: integer; f: single): integer;

      procedure PushCommand
          (
              pCommandStack: PStack;
              const aCommand: CBefehl
          );

    1. Each function is declared and commented on a seperate line. Different functions may be described in a single comment, if they differ only in their parameter lists and have the same responsibilities and functionalities.
    2. (C, C++) If a function has no parameters, the key word void must be used.
      1. void WasteTime(void);

    Function Definition

    1. When defining a function, each parameter is to write into a single line. Parameters must be commented. (C++) Default parameters are listed (and commented out).
    2. C/C++

      Pascal/Delphi

      void PushCommand
      // comments
          (
              PStack pCommandStack,
                  // list of executed commands
              const CCommand aCommand
                  // command to store
          )
      {
          Statements();
      }

      int SystemState
      // comments
          (
              const BOOL bErrorsOnly /* = TRUE */
                  // only errors are reported
          )
      {
          Statements();
      }

      procedure PushCommand
      // comments
          (
              PStack pCommandStack,
                  // list of executed commands
              const CCommand aCommand
                  // command to store
          )
      {
          Statements;
      }
    1. (C++) Initializers for data elements in a constructor are written in seperate lines.
      1. CComplex::CComplex
        //
        comments
            (void)
        : m_dfReal(0.0),
          m_dfImag(0.0)
        {
        }

    Function Call

    1. If possible, alle parameters in a function call are written into the same line.
    2. (C++) If a non-member function is called, it is preceeded by its scope.

    C++

    Pascal/Delphi

    if (0 < Std::strlen(lpszName))
    {
        Std::printf("Hello %s.", lpszName);
    }
    if (0 < System.Length(sName))
    begin
        System.Write('Hallo ', sName, '.');
    end {if};

    Types And Instances

    1. Each public variable is declared and commented in a seperate statement.
      1. int msg_nTotalNumberOfErrors = 0;    // Number of all errors that occurred.
        int msg_nPreviousNumberOfErrors = 0; // Number of errors that occurred since
                                             // previous call.

        Inadmissable:

          int msg_nTotalNumberOfErrors = 0, msg_nPreviousNumberOfErrors = 0;
              // Total and previous number of errors occurred.

    2. Each data element is declared and commented in a seperate statement.
      1. Inadmissable:

          private:
              CKlasse m_a, m_b, m_c;

    3. (C++) The declaration sections within classes are ordered as published – publicprotectedprivate. Within each section new definitions and types are followed by function elements and data elements are declared at the end of each section.
    4. (C++/Delphi) Exception: Properties may be declared after any other declaration, since properties may access private data elements.

        class CLineStyle
        {
            public:
                //-- constructors --//
                CLineStyle
                (
                        const int nLineStyle = SOLID_LINE,
                        const int nLinienWidth = NORM_WIDTH,
                        const unsigned uLinePattern = 0
                );
                //-- selectors --//
                int LineStyle(void) const;
                int LineWidth(void) const;
                unsigned LinePattern(void) const;
                //-- modifiers --//
                void UseLineStyle(const int nLineStyle);
                void UseLineWidth(const int nLineWidth);
                void UseLinePattern(const unsigned uLinePattern);
            protected:
                //-- agents --//
                virtual void Print(void);
                virtual void Draw(void);

            private:
                //-- Datenelemente --//
                int nLineStyle;
                unsigned m_uLinePattern;
                int m_nLineWidth;
        };

    5. (C++) Function declarations are grouped thematically. The groups are seperated by comments. Within these groups the polymorphic functions preceed the non-polymorphics. The Selectors should preceed the modifiers. The ordering of the topic groups is identical in each access section (public, protected, private, published).
    6. (Pascal/Delphi) Though the names of simple types (integer, double, etc.) are no key words in Pascal, they are written in lower case, so the notation is consistent to C/C++. Also, a confusing situation can be avoided:
      1. Inadmissable and confusing:

        var u: Cardinal;
        var n: Integer;
        var x: Double;

        n := Integer(u);  // Attention: A type cast here…
        u := Trunc(x);    // …but a function call this time!

        (slightly) better:

        n := integer(u);  // type cast
        u := Trunc(x);    // function call

    Modules

    1. (C/C++) The declaration file contains constant definitions, type definitions and function prototypes accessible to other modules. To avoid multiple #including, this file is framed by the following construct, :
      1. #ifndef _FILENAME_H
        #define _FILENAME_H
            ...
        #endif

    2. (C/C++) In the implementation file the declaration file is loaded (if necessary with other declaration files) by #include eingeladen. The functions declared in the declaration file are defined here. Private variables and functions are declared static.
    3. Modules may go without function definitions. If types and constants are defined only, the implementation file is dropped.
    4. (C, C++) It is forbidden to #include implementation files (.C bzw. .CPP).
    5. (C++) If template classes are implemented, the function definitions may be written into a seperate file. It has the extension .h.

    6. The correctness of modules is checked (supportingly) by the compiler. At the maximum warning level no messages must be generated.
    7. (C) If possible, and not supported by the compiler, a check has to be done by the lint tool.

    Comments


    [back] | [next] | [TOC] | [Introduction] | [Programming Style Guide] | [Annexes]


    Copyright © 1997-1998 by Uwe Sauerland