1.11.2. C99 Support

We presume C99 support for the C-Compiler to build the runtime system. But we don’t use all features of the C99 standard (details see below).

Note

Only use C99 features for new components or for components, for which a C99 feature is required! So don’t change existing components to C99 without a necessity!

1.11.2.1. Used features of C99 in the runtime system

  • Inline functions:

    static inline void swap(int *m, int *n)
    {
      int temp = *m;
      *m = *n;
      *n = temp;
    }
    
  • Intermingled declarations and code:

    Variable declaration is no longer restricted to file scope or the start of a compound statement (block).

  • Several new data types, including long long int, optional extended integer types, an explicit boolean data type, and a complex type to represent complex numbers:

    - _Bool:
    
        Boolean type
    
    - long long, long long int, signed long long, signed long long int:
    
        Signed 64 bit types
    
    - unsigned long long, unsigned long long int:
    
        Unsigned 64 bit types
    
  • Type-generic math (macro) functions, in <tgmath.h>, which select a math library function based upon float, double, or long double arguments, etc.:

    float_t, double_t:
    
        defined in <math.h>. Correspond to the types used for the intermediate results of floating-point expressions when FLT_EVAL_METHOD is 0, 1, or 2.
        These types may be wider than long double.
    
    float _Complex, double _Complex, long double _Complex:
    
  • Flexible array members:

    struct vectord
    {
        size_t len;
        double arr[]; /* the flexible array member must be last */
    };
    
    struct vectord *vector = malloc(sizeof(vectord) + array_len * sizeof(double));
    vector->len = array_len;
    
    for (int i = 0; i < vector->len; i++)
         vector->arr[i] = ...;
    
  • New library functions, such as snprintf / vsnprintf:

    vsnprint() is already used in the runtime system in the following macro:

    #define RTS_VSNPRINTF       vsnprintf
    
  • New headers:

    <inttypes.h>
    <stdbool.h>
    

    We use an own typesystem based on inttypes.h in the runtime system (see Datatypes)

  • Designated initializers:

    int a[6] = {[4] = 29, [2] = 15 }; or
    int a[6] = {[4]29 , [2]15 };
    

    Equivalent to:

    int a[6] = { 0, 0, 15, 0, 29, 0 };
    

    Initialize a range of elements to the same value:

    int a[] = {[0 ... 9] = 1, [10 ... 99] = 2, [100] = 3 };
    
  • Non-constant initializers:

    uint8_t g(void)
    {
        return 0x12;
    }
    
    uint8_t h(void)
    {
        return 0x34;
    }
    
    int foo(uint8_t data)
    {
           const uint8_t cmd[] = { 0x50, data, g(), h() };
           return send(cmd, sizeof(cmd));
    }
    

    Note

    Be careful because the calling order of initializer functions (example of g() and h()) is not defined and so avoid side effects in these initializing functions!

  • Compound literals (for instance, it is possible to construct structures in function calls:

    function((struct x) {1, 2}))]
    
  • Support for variadic macros (macros with a variable number of arguments):

    #define dbgprintf(...)  MyDebugOutput(__FILE__, __LINE__, __VA_ARGS__)
    

1.11.2.2. Unused features of C99 in the runtime system

Note

These features are not supported on the main targets of the runtime system, so they are prohibited in the code!

  • Variable-length arrays (although subsequently relegated in C11 to a conditional feature that implementations are not required to support)

    float read_and_process(int n)
    {
        float vals[n];
    
        for (int i = 0; i < n; ++i)
            vals[i] = read_val();
    
        return process(n, vals);
    }
    
  • New headers:

    <complex.h>
    
    <tgmath.h>
    
  • Single-line comments beginning with “//”:

    Reason: There are some compilers which still have problems with single-line comments! So only use standard C comments /* */ in the code!

    int nCounter = 0;   // Single comment line
    
  • Improved support for IEEE floating point

  • Universal character names, which allows user variables to contain other characters than the standard character set (“u” and “U”)

  • Restrict qualification allows more aggressive code optimization, removing compile-time array access advantages:

    With the keyword restrict you can mark 2 pointers for the compiler, that the memory location is different.

    void updatePtrs(size_t *ptrA, size_t *ptrB, size_t *val)
    {
      *ptrA += *val;
      *ptrB += *val;
    }
    
    void updatePtrs(size_t *restrict ptrA, size_t *restrict ptrB, size_t *restrict val);
    
  • Keyword static in array indices in parameter declarations:

    void foo(int arr [static 10]);       /* arr points to the first of at least
                                               10 ints                           */
    void foo(int arr [const 10]);        /* arr is a const pointer               */
    void foo(int arr [static const i]);  /* arr points to at least i ints;
                                               i is computed at runtime.         */
    void foo(int arr [const static i]);  /* alternate syntax to previous example */
    void foo(int arr [const]);           /* const pointer to int                 */
    

1.11.2.3. Tested C99-support of some C-Compilers

We checked some C-Compilers with the coverage of the C99 standard (state: 2019):

Shortname

Platform

Compiler Flags

Comment

TIDSP

TI DSP TIC28x

ti arm -O2

LINGCC

Linux x64

gcc -O0

Requires extern keyword for PURE_INLINE due to O0

CE6

Win CE6

Visual Studio 2005

not tested

CE7++

Win CE7

Visual Studio 2008, build as C++

Requires fix in test_helper.h (inline)

CE8++

Win CE8

Visual Studio 2013, build as C++

Aurix

Tricore Aurix TC299

Tasking VX v6.2r2

with Standard compiler flags

STM32Keil

Keil v5.06 ARM Compiler

–C99

VX 6.x

gcc 4.1.2

–std=C99

Possible compliant with gcc c99 status

gcc 4.3.3

VX 7.x

gcc 4.8.1

–std=C99

Possible compliant with gcc c99 status

LLVM-5.0.1

llvm-5.0.1 / cygwin x64, win10

requires extern keyword, requires fix for main() prototype

VS2015

Windows 10 64bit

Visual Studio 2015 - SP3

Here are the results:

Number

Feature

TIDSP

LINGCC

CE7++

CE8++

Aurix

STM32Keil

VX 6.8

LLVM-5.01

VS2015

A.0

CPP_COMMENTS

y

y

y

y

y

y

y

y

y

B.0

PURE_INLINE_FUNCTIONS

y

n

n

y

y

y

y

y

y

STATIC_INLINE_FUNCTIONS

y

y

n

y

y

y

y

y

y

C.0, C.1

MIXED_CODE_AND_DECLARATIONS

y

y

y

y

y

y

y

y

y

FOR_LOOP_INITIALIZERS

y

y

y

y

y

y

y

y

y

D.0, D.1, ..

DATATYPE_BOOL

y

y

n

n

y

y

y

y

y

DATATYPE_LONG_LONG

y

y

y

y

y

y

y

y

y

E.0, E.1

VAR_LEN_ARRAYS

n

n

n

FLEXIBLE_ARRAY_MEMBERS

y

y

n

y

y

y

y

y

y

F.0, F.1, ..

INCLUDE_INTTYPES

y

y

n

n

y

y

y

y

y

INCLUDE_STDBOOL

y

y

n

n

y

y

y

y

y

INCLUDE_COMPLEX

n

n

n

y

y

y

INCLUDE_TGMATH

n

n

n

y

y

n

G.0

TGMATH

n

n

n

H.0

IEEE_FLOAT

n

n

I.0, I.1

DESIGNATE_INITIALIZERS

y

y

n

n

y

y

y

y

y

NONCONST_INITIALIZERS

y

y

y

y

y

y

y

y

y

K.0

COMPOUND_LITERALS

y

y

n

n

y

y

y

y

y

L.0

VAR_MACROS

y

y

n

n

y

y

y

y

y

M.0

RESTRICT

y

y

n

n

y

y

y

y

n

N.0

UNIVERSAL_CHARACTERS

y

n

n

n

n

y

y

O.0

STATIC_ARRAY_INDEX

y

y

n

n

y

y

y

y

n