I can help you on your first point. The use of #ifdef
is to change what code is compiled based on previously configured information.
For example:
#define MAKE_SEVEN
#ifdef MAKE_SEVEN
int x = 7;
#else
int x = 9;
#endif
is _exactly the same as:
int x = 7;
as far as the compiler is concerned.
Why is this useful? Well, one reason is that you may want different code to be compiled for different machines, while still only having one copy of the source code.
Now this "configuration" can be set with a #define
or even as part of the command line for the compiler, like gcc -DMAKE_SEVEN ...
.
A more useful example than given above may be to use a different data type depending on the environment you're targeting. The code:
#ifdef INT_IS_32_BITS
typedef int int32;
#else
#ifdef LONG_IS_32_BITS
typedef long int32;
#else
#error No suitable type for int32 found
#endif
#endif
will allow you to use the correct type for a 32-bit integer type, for different architectures.
For all those an int
is 32 bits, you use gcc -DINT_IS_32_BITS ...
, for all those a long
is 32 bits, you use gcc -DLONG_IS_32_BITS ...
, for all others, the compiler will complain.