What are the things that I should keep in mind to write portable code? Since I'm a c++ beginner, I want to practice it since beginning.
Thanks.
What are the things that I should keep in mind to write portable code? Since I'm a c++ beginner, I want to practice it since beginning.
Thanks.
Use STL types when possible. Be careful of using system dependent types and APIs. For example don't use types like UINT, and DWORD on Windows.
You can use a library like boost to make it easier for you to write portable code. If you need a GUI consider using a cross platform toolkit like Qt.
Sometimes you will need to write platform specific code, and in those cases you can do something like this:
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
Write command-line programs to begin with. When you're ready, find a cross-platform windowing toolkit such as Qt.
If you're interested in writing multilingual code, use a third-party unicode library such as ICU rather than relying on platform-specific libraries.
For learning, try to avoid books that concentrate on one implementation. In some cases, the introduction or an early chapter will give you some instructions on how to get or use a language implementation; if it mentions more than one implementation you're probably OK.
Get a reference book that's platform-independent. Stroustrup's The C++ Programming Language is a fine reference, although it's not a good book for a beginner to try to learn from. Don't rely on references for a given implementation. MSDN is useful, for example, but its main focus is how to write Windows programs using Visual C++, not how to write programs that will compile and run anywhere.
To write anything really useful, you're going to have to get into nonportable code. Try to get in the habit of separating the user interface code from everything else, since that's where you'll have the least compatibility. The less code you have to change between platforms, the more portable your code is.
The unwary programmer is likely to walk into a whole lot of traps, that we can attempt to categorize. But let me tell you first: as an absolute it's impossible.
The problem is that even standard-conforming code might not be portable because of a particular compiler issue.
Now here are the main categories that I can think off the top of my head.
Compiler extensions
Like for example the use of variables arrays:
void func(int const n)
{
int array[n];
}
This is not standard, but many compilers support it nonetheless because it's just practical.
Standard libraries extensions
Many standard libraries implementations provide a std::hash_map
which never was specified. If you use it in your code, it's not portable.
The modern trend is to stash this stuff into the std::tr1
namespace so that programmers are aware that this is an extension.
Also be aware that many define typedef
or macros that are not generic (for example PRETTY_FUNCTION
). No macro is specified by the standard, and very few typedef are.
Platform specific
For example, the size and alignment of int
or double
is not specified in the standard. If you do bit-twiddling and expect it to have 32 bits, you'll be screwed on 64 bits platforms even without changing your compiler.
Platform API
Our programs are meant to be compiled, and they are often meant to interact with the computer they run on:
You need to find cross-platform portable APIs, or roll your own. Check some libraries in the list below.
Libraries
Most well-written libraries are largely portable, just make sure that they support:
Good libraries involve:
The others you need to review... and that takes time.
I don't think there is a perfect answer there. But since perfect portability is not possible you need to decide which compilers and platform you wish to support.
For the platform, you should begin with Windows and one Linux flavor. For the compilers, pick any two (with Comeau if you can afford it).
a good idea is to use POSIX system calls. that way you don't have to deal with different ways of creating threads or using mutexes and signals.
the problem is that Windows is not exactly POSIX compliant, but there are libraries that implement certain POSIX features, like this one: [1]: http://sourceware.org/pthreads-win32/
Keep platform-specific code separate from reusable code, preferably in a different file but at least in a different function. If you start having #if WIN32
and #if CYGWIN
and #if BSD
all over the place you'll have a maintenance nightmare.
Then, compile on at least two different platforms early and often. Typical choices are Visual C++ on Windows and gcc on Linux. Since neither the system libraries nor the compiler is shared, you'll catch non-portable code before it becomes deeply entrenched in your design.
OS-independent code is surprisingly hard to do in C++. Consider this trivial example:
#include <iostream>
int main(int argc, char** argv) {
std::cout << argv[0] << std::endl;
}
That is perfectly valid C++, still it's nonportable because it won't accept Unicode command line arguments on Windows. The correct version for Windows would be:
#include <iostream>
int wmain(int argc, wchar_t** argv) {
std::wcout << argv[0] << std::endl;
}
Of course that is again nonportable, working only on Windows and being nonstandard. So in fact you cannot even write a portable main()
function in C++ without resorting to conditional compilation.
Some guidelines:
Sometimes you have to trade off efficiency and performance to gain portability. For example, if your code requires accessing fields out of a buffer you can always cast a packed struct to the buffer pointer. But that is horribly non-portable. So instead you need to use named pointers calculated with offsets -- sometimes with boundary alignment handling code. Not pretty, but portable. Fortunately you can hide a lot of that stuff with judicious use of class interfaces.
Not all code needs to be written that way. If you design your application in a very modular way with well defined boundaries of responsibility then 90-95% of the code can be portable without pain. Then just isolate the 5-10% in a very localized area that would need to be customized for a new platform.
If you can, compile all your code with at least two different compilers.
Others said it before, but here is my view on it:
1) Do you need C++? It's not the best language for writing portable code because it's close to the bare metal. Java, Python, Perl, PHP or Javascript might be better for you.
2) If you need C++, don't try to write completely portable code, it's almost impossible anyway. Instead, decide early which platforms you want to support. For example: Linux, MacOS X, Windows
3) Make sure you test your code on all selected platforms continously. Don't just build on Windows and expect to just compile a Linux version 'when it's done'. Compile on all platforms daily and make sure you keep testing them for problems.
What are the things that I should keep in mind to write portable code?