Zaid
Zaid

Reputation: 37136

Why should one bother with preprocessor directives?

This question may seem rather basic, but coming from an engineering (non computer-science) background, I was unsure about what the snippets of '#'s were in some C++ code.

A quick search led me to the concise, well-explained cplusplus tutorial page on preprocessor directives.

But why bother with the concept of preprocessor directives at all? Is it not possible to write equivalent code that can assign values to constants, define subroutines/function/macros and handle errors?

I guess I ultimately want to know when it is good practice to use such preprocessor directives, and when it is not.

Upvotes: 28

Views: 11729

Answers (14)

user13947194
user13947194

Reputation: 402

Unlike everybody else, I don't have a big problem with preprocessor directives. The only thing is that using preprocessor defines works better in C than C++. Eg: Win32, OpenGL, zip libraries, jni and many other c libraries use preprocessor directives. Eg: Win32 has "OPAQUE" and "TRANSPARENT" which is passed to their function SetBkMode(HDC,int); Now imagine how easily it is to want to use any of those words. You can't, because C preprocessor doesn't care about namespace. Why isn't there a Cpp preprocessor.

But I know the right tool for job.

Upvotes: -1

T.E.D.
T.E.D.

Reputation: 44794

Generally, preprocessor directives should not be used. Sadly, sometimes you have to in C and C++.

C originally defined the language in such a way that you really couldn't do anything serious with it without using the preprocessor. The language had no other built in support for creating modular programs, constants, inlined code, or to do generic programming.

C++ gets rid of most of these issues but the facility is still there, so it still gets used. (Interestingly, not the modularization one. We're still stuck with #include),

If you want to compare with a language built at a similar-level of abstraction for similar tasks that does not have a preprocessor, go take a look at Ada.

Upvotes: 2

hookenz
hookenz

Reputation: 38879

Preprocessing occurs before the code is compiled. It's appropriate in cases like the following

#ifdef WIN32
#include <something.h>
#elseif LINUX
#include <somethingelse.h>
#endif

Obviously including header files you want done at compilation time not runtime. We can't do this with variables.

On the other hand. With C++ it is good practice and greatly encouraged to replace constant expressions like the following example

#define PI 3.141592654
with
const double PI=3.141592654;

The reason is that you get proper typecasting and datatype handling.

Also

#define MAX(x,y) (x) > (y) ? (x) : (y)

Is not very nice because you can write

int i = 5
int max = MAX(i++, 6);

The preprocessor would replace that with:

int max = (i++) > (6) ? (i++) : (6);

Which is clearly not going to give the intended result.

Instead, MAX should be a function (not a macro). If it's a function it can also provide the type in the parameter.

I have seen the preprocessor used for all sorts of interesting things. Like language keyword declaration. It can aid in readability in this case.

In short, use the preprocessor for things that must happen at compile type such as conditional includes directives. Avoid using it for constants. Avoid macros and instead use functions where possible.

Upvotes: 8

RC.
RC.

Reputation: 28197

You use preprocessor directives when you need to do something outside of the scope of the actual application. For instance, you'll see preprocessing done to include or not include code based on the architecture the executable is being built for. For example:

#ifdef _WIN32 // _WIN32 is defined by Windows 32 compilers
#include <windows.h>
#else
#include <unistd.h>
#endif

Preprocessor directives are also used to guard includes so that classes/functions etc. are not defined more than once.

#ifndef MY_CLASS_6C1147A1_BE88_46d8_A713_64973C9A2DB7_H_
#define MY_CLASS_6C1147A1_BE88_46d8_A713_64973C9A2DB7_H_
    class MyClass {
    ....
    };
#endif

Another use is for embedding versioning inside of code and libraries.

In the Makefile you have something along the lines of:

-D MY_APP_VERSION=4.5.1

While in the code you have

cout << "My application name version: " << MY_APP_VERSION << endl;

Upvotes: 31

Charles Salvia
Charles Salvia

Reputation: 53289

Many programming languages have meta-programming facilities, where you write code for the compiler to follow, rather than the runtime environment.

For example, in C++, we have templates which allow us to instruct the compiler to generate certain code based on a type, or even a compile-time constant. Lisp is perhaps the most famous example of a language with advanced meta-programming facilities.

C preprocessor directives/macros are just another form of "meta-programming", albeit a relatively cruder form than is available in other languages. Preprocessor directives instruct the compiler to do certain things at compile time, such as to ignore certain code on certain platforms, or to find and replace a string in the code with another string. This would be impossible to do at runtime, after your code is already compiled.

So essentially, the C-preprocessor is an early form of "meta-programming", or compiler-programming.

Upvotes: 3

David Thornley
David Thornley

Reputation: 57036

A bit of history here: C++ was developed from C, which needed the preprocessor a lot more than C++ did. For example, to define a constant in C++, you'd write something like const int foo = 4;, for example, instead of #define FOO 4 which is the rough C equivalent. Unfortunately, too many people brought their preprocessor habits from C to C++.

There are several reasonable uses of the preprocessor in C++. Using #include for header files is pretty much necessary. It's also useful for conditional compilation, including header include guards, so it's possible to #include a header several times (such as in different headers) and have it processed only once. The assert statement is actually a preprocessor macro, and there are a few similar uses.

Aside from those, there are darn few legitimate uses in C++.

Upvotes: 2

Clifford
Clifford

Reputation: 93456

The C preprocessor performs a number of tasks, some but not all of which have better alternatives in C++. Where C++ has a better alternative use it. Those alternatives include templates, inlining, and const variables (an oxymoron, but that is what the standard calls them) in place of #define macros.

However there are few things that you would not want to do without or simply cannot do without; #include for example is essential, and when coding for multiple platforms or configurations, conditional compilation remains useful (although should be used sparingly in all cases).

Compiler specific extensions controlled via #pragma may be unavoidable in some cases.

Upvotes: 0

justin
justin

Reputation: 104698

But why bother with the concept of preprocessor directives at all? Is it not possible to write equivalent code that can assign values to constants, define subroutines/function/macros and handle errors?

Its use is very low in C++, features of the language were created to avoid problems associated with the preprocessor.

I guess I ultimately want to know when it is good practice to use such preprocessor directives, and when it is not.

In general C++ sources, it is often seen as poor practice - particularly when there is a mean to do it using other language features. It is required for some things (i.e. platform/build dependent programs and generative programs). In short, there's usually a replacement which scales well. (such as constant define as enum, or inline templates instead of macros). If you find yourself using one and you are not sure, then just ask/search if there is a better way to declare this_code_snippet in C++, without the preprocessor.

Upvotes: 1

Dima
Dima

Reputation: 39389

Answered here.

Upvotes: 0

Daniel Pryden
Daniel Pryden

Reputation: 60927

Because preprocessor directives get executed at build time, while code you write will get executed at run time. So preprocessor directives effectively give you the ability to modify your source code programmatically.

Note that the C preprocessor is a rather crude mechanism for this kind of thing; C++'s template system provides a much more powerful framework for compile-time construction of code. Other languages have even more powerful metaprogramming features (for example, Lisp's macro system).

Upvotes: 7

Macke
Macke

Reputation: 25680

It's a better-than-nothing substitute to get some reflection capabilities out of C++.

Very useful to generate variables and strings with the same names.

Upvotes: 0

alexkr
alexkr

Reputation: 4670

It is used most frequently for two things which will be harder to organize without it:

  1. Include guards.
  2. Different sections of code for different platforms.

Upvotes: 6

Earlz
Earlz

Reputation: 63805

No, it actually is not possible to get by without the preprocessor in all cases. One of my favorite macros is

#define IFDEBUG if(DEBUG==1)
//usage:
IFDEBUG{
  printf("Dump of stuff:.,,,");
}else{
  //..do release stuff
}

Without macros, I would have (possibly a lot) space wasted in the final executable

And also you must realize, C/C++ doesn't have any sort of package type require or other such system. So without the preprocessor, there is no way of preventing code-duplication. (header files can't be included)

Upvotes: 1

bmargulies
bmargulies

Reputation: 100003

Answer 1: conditional code that has to vary depending on what sort of computer it works on.

Answer 2: enabling and disabling language extensions and compatibility features seen at compile time.

The preprocessor came from C, where there were many thing you could not express. Good C++ code finds less reasons to use it than C code did, but sadly it's not quite useless.

Upvotes: 10

Related Questions