Page 1 of 1

Introduction to the Preprocessor Rate Topic: -----

#1 RodgerB  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 66
  • View blog
  • Posts: 2,284
  • Joined: 21-September 07

Post icon  Posted 20 October 2007 - 11:26 PM

In this tutorial we will learn how to use the Preprocessor efficiently and learn some nice tips when using it. This tutorial is aimed at Beginning - Intermediate programmers.

In this tutorial we will be covering:
  • Using Define's to return values
  • Adding Parameters to your defines
  • How to include using the #include function
  • Using the preprocessor's if statements

1. Using Defines to return values.

This is the primary function of a define, a macro that tells the compiler this is what I want this value to be. But, how do I use the #define macro?

#define <define name> <value>


Replace <define name> with a name of your choice, for example DRIPPING_TAP (Note that there can't be spaces), and <value> to a value of your choice. This value can be a string, integer, float, double, hex, etc value etc. But for now we are just going to use 1.

Example 1.1:
#define DRIPPING_TAP 1


Now that we have our define, we may as well use it or that would be retarded :P. You can use a define of this kind like any constant variable, you can read it, you can't write to it. In example 1.2, you can see how this can be used.

Example 1.2:
#define DRIPPING_TAP 1

int main()
{
	if(DRIPPING_TAP) // If DRIPPING_TAP is true
	{
		printf("It is true.");
	}
}



Try experimenting with different values and ways they can be used, you'll be suprised how powerful the #define function really is.

2. Adding Parameters to your defines.

In this section we will learn how to use our define blocks like a function. Using defines as a function generally more efficient as everything is handled by the preprocessor. The beauty of this is it doesn't require any forward declarations, and takes less memory.

We can use bitwise operations for if statements, and make use of C++'s operators effectively. Here is an example of a max() macro:

#define max(a,b) a > b ? a : b


In English: If a more than b equals true return a, else return b. This function checks two numbers, and returns the biggest one.

Say we have 3 variables called x, y and z. This is what it would look like before preprocessing.
z = max(x,y);


This is what it would look like after preprocessing.
z = x > y ? x : y;


Lets look at another macro.

#define IsNumberOdd(val) val % 2


We make the val parameter like any other function, and use the modulus sign to get the remainder of a division by 2. And because a number can only be either odd or even, you can use that for this two. Example 2.1 will demonstrate how you can make your code more clear.

Example 2.1
#define NUMBER_ODD 1
#define NUMBER_EVEN 0
#define IsNumberOdd(val) val % 2

int main()
{
	int Number = 100;
	if(IsNumberOdd(Number) == NUMBER_ODD) printf("%d is odd.", Number);
	else if(IsNumberOdd(Number) == NUMBER_EVEN) printf("%d is even.", Number);
}



3. Including a file

Many beginners get stuck into thinking that they need to place there include files in the default directory. The most general way of including a file is #include <..>, but you can choose to include a file inside your project's directory with the almighty preprocessor. #include ".." will set it so the compiler will look in the project's directory not the default one.

4. Using the preprocessor's if statements.

The preprocessor has a lot of useful ways of testing values. Here is an example of how you can check if the computer is running windows.

int main()
{
#if defined(WIN32)
	print("Windows");
#else
	print("Not windows");
#endif
}



There are a lot of other useful definitions out there, and I hope you have learnt at least something about the preprocessor from this tutorial. :)

Is This A Good Question/Topic? 0
  • +

Replies To: Introduction to the Preprocessor

#2 NickDMax  Icon User is offline

  • Can grep dead trees!
  • member icon

Reputation: 2247
  • View blog
  • Posts: 9,237
  • Joined: 18-February 07

Posted 12 February 2008 - 09:27 AM

Just a note: In programming we deal with binary much more than we realize. Sure we all get our introduction to binary numbers and binary logic but we don't always think to apply the lessons.

Take this bit of code that I have written several time, in several languages:
return (some complicated condition) ? true : false;
Now see I thought I was being smart and translating some complicated expression into a binary value -- BUT as it turns out it was already a binary value!!! A condition is either true, or false -- there is no "maybe" in C/C++ conditions.

So the code example above:
#define NUMBER_ODD 1
#define NUMBER_EVEN 0
#define IsNumberOdd(val) val % 2

int main()
{
	int Number = 100;
	if(IsNumberOdd(Number) == NUMBER_ODD) printf("%d is odd.", Number);
	else if(IsNumberOdd(Number) == NUMBER_EVEN) printf("%d is even.", Number);
}


The IsNumberOdd macro creates a binary distinction: a number is either even, or its odd. There is no other choice. So you can simplify your code to at least:
#define NUMBER_ODD 1
#define NUMBER_EVEN 0
#define IsNumberOdd(val) val % 2

int main()
{
	int Number = 100;
	if(IsNumberOdd(Number) == NUMBER_ODD) printf("%d is odd.", Number);
	else printf("%d is even.", Number);
}


Now as another layer of weirdness, in C/C++ a zero in false, and a non-zero is true. So you can simplify the code to:
#define NUMBER_ODD 1
#define NUMBER_EVEN 0
#define IsNumberOdd(val) val % 2

int main()
{
	int Number = 100;
	if(IsNumberOdd(Number)) printf("%d is odd.", Number);
	else printf("%d is even.", Number);
}


Granted this is really just semantics since chances are the compiler is going to simplify your expressions for you and compile the same code for all three -- and it was nice to have the big bold "NUMBER_ODD" to remind us that the number is odd.

I would also like to note that one should use a naming convention when creating macros (in the C/C++ world macros are normally named in all upper case). The reason is to remind programmer that they are using a macro no a function. Since a macro is a direct substitution there can be unintended consequences when using them:

maxVal = MAX(a++, b++);
becomes
maxVal = (a++ > b++) ? a++ : b++;
which actually has undefined behavior (can change from compiler to compiler). but the programmer may have been expecting the macro to be a function like:
inline int max(int a, int b) { return (a > b) ? a : b; }
which would have found the max between a & b and then incremented both a, b.

So to give programmers a fair chance at catching these VERY hard to find bugs, you generally want to distinguish between what is a macro and what is a function.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1