C/C++ are nice low level, high-performance languages if you need to be “close to the metal” due to performance or memory constraints. Nevertheless, C/C++ are portable languages because they provide datatypes to abstract from the underlying hardware and compilers for virtually every hardware platform. It is very easy to kill portability because the specification allows certain platform-dependent sizes for the built-in datatypes. An
int can be 16 bits or 32 bits, a
long 32 bits or 64 bit and so on. Many programmers mitigate the issue by defining own datatypes like
uint32. If you are using some libraries it is very likely that several such type definitions are available and often times interchangeable.
It is absolutely crucial to be consistent when using the type definitions and usually a good advice not to use the built-in types like int or long because they will change in size on different platforms.
In one of our projects we are working on Tango device servers written in C++ and use the YAT (Yet Another Toolbox) library. There are at least 3 possible ways in this small project to define a (most of the time) unsigned 32 bit word:
- unsigned long
To make matters a bit more interesting the tango::DevUlong is defined by the CORBA C++ mapping. Code using all of these definitions may work on a certain platform so you will not notice the problem right away, but we had several compilation problems and even program crashes when compiling or running on Linux/x86, Linux/AMD64, Windows 7 32bit and Windows 7 64bit. Using types that guarantee their size on all platforms and consistent usage of them will make your code compile and run on many platforms flawlessly.
One thought on “Inconsistent usage of type definitions kills portability in C/C++”
Very true, I’m currently working on a project that was first written years ago. Some guys of the team got new 64 bits computers, and the soft crashes while it worked perfectly on 32 bits. Highly probable that an assumption on the size of int or long is responsible for that.
However, I think such an article should at least talk about stdint.h header, that defines uint32_t and friends. This is THE standard C99 (and C++ through cstdint) way to have fixed length integer. The fact that a standard way exists (it’s been 12 years now !) should make any other hack or project-wide definition obsolete (unless there is a code base that cannot be changed, or a painful development envronment).