Tips and Tricks – Writing Portable Code using Compiler Intrinsics

All preprocessor directives are not created equal. A developer will have different preprocessor directives available depending on whether GNU C, IAR Embedded Workbench, Keil uVision or any other compiler is used. ANSI-C has a limited number of preprocessor directives that are included in the standard and can be considered portable.

Compiler vendors have the ability to add preprocessor directives that are not part of the standard. For example, #warning is a commonly used preprocessor directive that is not supported by C90 or C99! The #error preprocessor directive is part of the standard and #warning was added by compiler vendors in order to allow a developer to raise a compilation warning. Developers who rely heavily on #warning may port code to a compiler that doesn’t recognize #warning as a valid preprocessor directive or may recognize it as having a different purpose!

A developer interested in writing portable code needs to be careful which preprocessor directives are used within the embedded software. The most obvious non-portable preprocessor directive is #pragma which can generally be considered to declare implementation-defined behaviors within an application. The use of #pragma should be avoided as much as possible within an application that is expected to be ported to other tool chains.

The use of #pragma or other specialized preprocessor directives cannot always be avoided. One example where #pragma may be necessary is to specify an optimization that should be performed on an area of code. A developer in a similar situation can use compiler predefined macros and conditional compilation to ensure that the code is optimized and that if it is ever ported to another compiler an error is raised at compile time. Each compiler has its own set of predefined macros including a macro that can be used to identify the compiler that is in use. Figure 1 shows an example of a few compiler defined macros that may be of interest to a developer.

Intrinsic1Figure 1 – Compiler defined macros

 The predefined macros from Figure 1 that identify the compiler can be used as part of a preprocessor directive to conditionally compile code. Each compiler that may be used can then be added to the conditional statement with the non-portable preprocessor directive that is needed for the task at hand. Figure 2 shows how a developer might take advantage of the predefined compiler macros to conditionally compile a fictitious #pragma statement into a code base.

Intrinsic2 Figure 2 – Using conditional compilation for non-portable constructs

 Developers interested in writing portable, ANSI-C code should consult the ANSI-C standard, such as C90, C99 or C11, and check the appendices for implementation defined behaviors.

Leave a Reply

Your email address will not be published. Required fields are marked *