C Prepocessor hard to understand and very confused.

Jan 1, 2010 at 2:11am
I'm having a REALLY hard time understanding preprocessors.

Now I know the situation where you want to "define" something using the #define preprocessor such as #define PI 3.14

that would change all the ("PI") words in your code into 3.14 right?


Well what about #define _MATH_H_


that I have no idea what is happening. In the math library it says

#ifndef _MATH_H_
#define _MATH_H_


code here


#endif


can you explain to me what is happening? Please in detail!
Jan 1, 2010 at 2:30am
That just basically sets some preprocessor "variable" if you want to call it that, to exist, so if you later check #ifdef it will be true.
Jan 1, 2010 at 2:35am
so why would i ever need to use that in a program? What will happen if i don't.


I'm having some problems creating a RPG game because of this stuff. Can you explain in detail what's happening? Or possibly give me an easy to read tutorial on it?

Jan 1, 2010 at 2:48am
#ifdef and #ifndef check to see if the symbol has been defined. #ifdef then includes everything up to an #else or an #endif if the symbol has been defined, while #ifndef includes everything if the symbol has not been defined.

So, in your example, the first time you include math.h, assuming that is the name of that file, the pre-processor will find the #ifndef _MATH_H_ line, find that it has not been defined and continue including code.

The next line then defines _MATH_H_ as the default value, which should be 1.

If you then try to include math.h again, the pre-processor will get to the #ifndef line, discover that _MATH_H_ has been defined and skip to the #endif.


so why would i ever need to use that in a program? What will happen if i don't.

Well, People do this to stop a header file from being included multiple times.

example.h
1
2
3
4
5
6
#ifndef _EXAMPLE_H
#define _ EXAMPLE_H

int exampi = 0;

#endif 


example.c
1
2
3
4
#include "example.h"
#include "example.h"

...


This example then, tries to include example.h twice, however, the second time it tries, it discovers that _EXAMPLE_H has been defined, and skips to the #endif, thus stopping the file from being included twice. If you didn't have this code the compiler would spit errors about defining the same variable twice.
Last edited on Jan 1, 2010 at 2:57am
Jan 1, 2010 at 3:32am
oh thank you arathalion that was very helpful. However one more question that has been bugging me in the back of my mind for a very long time. What does it mean to "define" something?

As you said right above your 2 examples and the quote "If you then try to include math.h again, the pre-processor will get to the #ifndef line, discover that _MATH_H_ has been defined and skip to the #endif."

what do you mean by "has been defined"

does that mean that the compiler has already compiled that? ... or.. what. i'm confused
Jan 1, 2010 at 3:42am
Before I get started -- please note that macros are evil and you should generally avoid #define where possible. It's fine to use for include guards (ie: the whole _MATH_H_ thing), but apart from that it's kind of sketchy. So don't make a habit of putting #define everywhere.


"Define" doesn't really mean anything special, it just means that the preprocessor recognizes the word as a symbol. Here's an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
using namespace std;

int main()
{
#ifndef TEST
  cout << "test 1\n";
#endif

#define TEST

#ifndef TEST
  cout << "test 2\n";
#endif
}


If you run this, you'll fine that "test 1" will print, but not "test 2". This is because TEST was not defined until the #define line.
Jan 1, 2010 at 9:58am
Why, exactly, are macros evil? I use them all the time and rarely have any problems with them.
Jan 1, 2010 at 10:23am
Jan 1, 2010 at 10:23am
I think they're just bad practice... Partly, I guess, because they're unnecessary. You'd be better off using inline functions and constants in most cases.

I use them, but not "all the time." I use them for things like header guards (obviously), and also for debugging. They're useful for trying out two pieces of code separately, like this:
1
2
3
4
5
6
7
8
9
#if __DEBUG == 1 || __DEBUG == 0
foo();
#endif

/* More code */

#if __DEBUG == 2 || __DEBUG == 0
bar();
#endif 

In that case you could compile foo(), bar() or foo and bar() by defining __DEBUG to 1, 2 or 0 respectively (I'd use 3, but making 0 the option to compile all code allows you to add as many of those #if-endif blocks as you want without changing those that are already there).

@Bazzy,
That guy says pointers are evil. I most heartily disagree.
Last edited on Jan 1, 2010 at 10:30am
Jan 1, 2010 at 10:35am
http://www.parashift.com/c++-faq-lite/big-picture.html#faq-6.15 :
C programmers who are new to C++ often use pointers, arrays and/or #define more than they should.
...
The goal of farcical things like "pointers are evil" is to convince new C++ programmers that C++ really isn't "just like C except for those silly // comments."
Everything is evil if used improperly or when you have a better alternative
Last edited on Jan 1, 2010 at 10:36am
Jan 1, 2010 at 10:39am
I see...
Jan 1, 2010 at 12:06pm
Hey thanks , I didn't know that. :P
Know I can code normal again! I always had to strugle to find what made the header file be included multibple times! :P
Last edited on Jan 1, 2010 at 2:59pm
Topic archived. No new replies allowed.