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.
Figure 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.
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.
Struggling to keep your development skills up to date or facing outdated processes that slow down your team, raise costs, and impact product quality?
Here are 4 ways I can help you:
- Embedded Software Academy: Enhance your skills, streamline your processes, and elevate your architecture. Join my academy for on-demand, hands-on workshops and cutting-edge development resources designed to transform your career and keep you ahead of the curve.
- Consulting Services: Get personalized, expert guidance to streamline your development processes, boost efficiency, and achieve your project goals faster. Partner with us to unlock your team's full potential and drive innovation, ensuring your projects success.
- Team Training and Development: Empower your team with the latest best practices in embedded software. Our expert-led training sessions will equip your team with the skills and knowledge to excel, innovate, and drive your projects to success.
- Customized Design Solutions: Get design and development assistance to enhance efficiency, ensure robust testing, and streamline your development pipeline, driving your projects success.
Take action today to upgrade your skills, optimize your team, and achieve success.