473,385 Members | 1,400 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,385 software developers and data experts.

Opinion: macros and why they're bad

In a recent post ("About C error" by Victor, 21 Sep 2003), comments were
made about the poster's use of macros. What I would like to know is why
they are considered bad? I'm not referring to their use as 'functions'; I
realise the loss of type-safety and the possible evaluation errors that can
occur. However, what would be the harm with numeric and text literals?

Consider a number that plays a significant role in the implementation of an
algorithm, and in that implementation the number is required in two, or
more, different scopes. There wouldn't be much point in declaring a
const-qualified variable in both scopes as it spoils a benefit of
identifying such 'magic' numbers - defining it in a single, easily locatable
position (for maintenance). In such a case, would you even consider waiving
the 'no globals' recommendation just to avoid the use of a macro?

Would performance, or in fact anything, really be adversely affected by the
use of a macro instead of a const-qualified variable?

Just out of plain curiosity (as I use macros, as described above, myself),
Mike

--
Michael Winter
M.Winter@[no-spam]blueyonder.co.uk (remove [no-spam] to reply)
The comments I refer to follow. Please note that no offence to the posters
is intended. I am simply using their comments as examples (I don't have any
others to hand).
Kevin Goodsell (in response to the original post):
#define MAXVERTICES (20) /*Maximum number of object's vertices*/
#define MAXFILENAME (20) /*Maximum characters of file's name*/
#define MAXDATA (40) //Maximum data can be read
#define M (256)
#define N (256)
Macros are bad.

-----
Jack Klein (in response to the original post):
#define MAXVERTICES (20) /*Maximum number of object's vertices*/
#define MAXFILENAME (20) /*Maximum characters of file's name*/
#define MAXDATA (40) //Maximum data can be read
#define M (256)
#define N (256)


Why are you putting parentheses around simple text macros like this?
It can't do you any good, and it just might cause problems in some
instances, although I can't think of any off-hand.

Since you are compiling with a C++ compiler, why not use constant
variables instead?
Jul 19 '05 #1
8 7202
Michael Winter wrote:
In a recent post ("About C error" by Victor, 21 Sep 2003), comments were
made about the poster's use of macros. What I would like to know is why
they are considered bad? I'm not referring to their use as 'functions'; I
realise the loss of type-safety and the possible evaluation errors that can
occur. However, what would be the harm with numeric and text literals?

Consider a number that plays a significant role in the implementation of an
algorithm, and in that implementation the number is required in two, or
more, different scopes. There wouldn't be much point in declaring a
const-qualified variable in both scopes as it spoils a benefit of
identifying such 'magic' numbers - defining it in a single, easily locatable
position (for maintenance). In such a case, would you even consider waiving
the 'no globals' recommendation just to avoid the use of a macro?
A global variable is certainly preferable to a macro.

Would performance, or in fact anything, really be adversely affected by the
use of a macro instead of a const-qualified variable?

Just out of plain curiosity (as I use macros, as described above, myself),


Macros modify the code "behind your back" before the compiler sees it.
This makes problems harder to locate.

Macros require more care when defining them, so they allow more
opportunity for mistakes:

#define SUM = a + b // woops, forgot parens
int val = SUM * 2; // wrong result

Macros don't obey scoping rules.

#define my_const 5

void func()
{
const int my_const = 7; // woops, error.
}

Macros can be redefined.

// my_header.h
#define MY_IMPORTANT_CONSTANT 42

// some_header.h
#undef MY_IMPORTANT_CONSTANT
#define MY_IMPORTANT_CONSTANT 3

// main.cpp
#include "my_header.h"
#include "some_header.h"

Macros don't have types.

#define NULL_PTR 0
void f(int);
void f(char *);

f(NULL_PTR); // woops, probably calling the wrong function

// another example:

#define MY_STRING "This is a string"

char *p = MY_STRING; // woops! Could have been diagnosed
// if const had been used

Most uses of macros can be replaced with language features that are
better-behaved, so why would you want to stick with macros?

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Jul 19 '05 #2
On Sun, 21 Sep 2003 23:34:14 GMT, "Michael Winter" <M.Winter@[no-spam]blueyonder.co.uk> wrote:
In a recent post ("About C error" by Victor, 21 Sep 2003), comments were
made about the poster's use of macros. What I would like to know is why
they are considered bad?
Because macros are text substitution, and since macros don't live in
namespaces you cannot avoid the ones you don't want.

Concrete example: Microsoft's GDI+ graphics API has a header file that
requires macros "min" and "max", which clash with the standard C++ library.

Also, macros are not type-safe, not evaluation safe (esp. wrt. side effects),
not suited for debugging, do not follow ordinary syntax neither in definition
nor in usage, and and and.

I'm not referring to their use as 'functions'; I
realise the loss of type-safety and the possible evaluation errors that can
occur. However, what would be the harm with numeric and text literals?
See above.

Consider a number that plays a significant role in the implementation of an
algorithm, and in that implementation the number is required in two, or
more, different scopes. There wouldn't be much point in declaring a
const-qualified variable in both scopes as it spoils a benefit of
identifying such 'magic' numbers - defining it in a single, easily locatable
position (for maintenance). In such a case, would you even consider waiving
the 'no globals' recommendation just to avoid the use of a macro?
There is no recommendation to avoid global constants. It's a good idea to
put them in a namespace, though, if they're going to be used in more than
one compilation unit. In short, there's no need for macros for that.

Would performance, or in fact anything, really be adversely affected by the
use of a macro instead of a const-qualified variable?
See above.
Just out of plain curiosity (as I use macros, as described above, myself),


Don't. ;-)

Macros are sometimes necessary, but not for things which there are very
good language constructs for.

* DON'T: #define MYTEXT "Pling plong"
DO: char const myText[] = "Pling Plong";

* DON'T: #define NMAX 5
DO: std::size_t const nMax = 5;

* DON'T: #define SQUARE( x ) (x)*(x)
DO: template<typename T> T inline square( T x ){ return x*x; }

And so on.

Jul 19 '05 #3
Michael Winter <M.Winter@[no-spam]blueyonder.co.uk> wrote in message
news:Wz*********************@news-text.cableinet.net...
In a recent post ("About C error" by Victor, 21 Sep 2003), comments were
made about the poster's use of macros. What I would like to know is why
they are considered bad? I'm not referring to their use as 'functions'; I
realise the loss of type-safety and the possible evaluation errors that can occur. However, what would be the harm with numeric and text literals?

Consider a number that plays a significant role in the implementation of an algorithm, and in that implementation the number is required in two, or
more, different scopes. There wouldn't be much point in declaring a
const-qualified variable in both scopes as it spoils a benefit of
identifying such 'magic' numbers - defining it in a single, easily locatable position (for maintenance). In such a case, would you even consider waiving the 'no globals' recommendation just to avoid the use of a macro?
The argument is mostly against global _variables_, not global constants. Why
do you think a global constant is bad but a global macro is okay? Anyway,
you can put a constant in a namespace if you want. You can't confine a
macro's scope at all.
Would performance, or in fact anything, really be adversely affected by the use of a macro instead of a const-qualified variable?

Just out of plain curiosity (as I use macros, as described above, myself),


Macros are a text-replacement facility. If you use them, the source code you
see isn't what the C++ parser gets. Try compiling this:
#define WIDTH 5.6
#define HEIGHT 4..1
#define DEPTH 7.9

void f()
{
double volume = WIDTH*HEIGHT*DEPTH;
//...
}

VC++ 6.0 says:
z.cpp(7) : error C2143: syntax error : missing ';' before 'constant'

Line 7 is perfectly in order, but this is what you get for using macros. If
you replace the macros with:

const double WIDTH = 5.6;
const double HEIGHT = 4..1;
const double DEPTH = 7.9;

VC++ 6.0 says:
z.cpp(2) : error C2143: syntax error : missing ';' before 'constant'

At least you now know where the error really is.

It seems self-evident that the more different the code you edit is from the
code received by the C++ parser, the more problems you are going to get in
code maintenance, compiling and debugging.

DW

Jul 19 '05 #4
OK guys... can you come up with an easy, non macro way, to perform the
following ?
#ifdef DATALOGGER_ACTIVE

#pragma message ( "Compiling with Data Logger" )

#define PUT_MSG( errorName, functionName, Data ) \
DataLogger::Put ( errorName, \
MacroComponentName + CString ( "." ) + MacroClassName, \
functionName, \
Data ) ;

#else

#pragma message ( "Compiling without Data Logger" )

#define PUT_MSG( errorName, functionName, Data )
#endif

This macro PUT_MSG is used throughout the code to provide a multi level data
loggin mechanism to monitor the application during runtime. It is
controllable on an individual compilation unit level, so as a level
completes dubugging and test you can set DATALOGGER_ACTIVE to false and all
of the code associated with the logging calls get removed from the
application.
How would I accomplish this without mcaros ?

Thanks
Joe Simon
Jul 19 '05 #5
Joe Simon wrote:
OK guys... can you come up with an easy, non macro way, to perform the
following ?
#ifdef DATALOGGER_ACTIVE

#pragma message ( "Compiling with Data Logger" )

#define PUT_MSG( errorName, functionName, Data ) \
DataLogger::Put ( errorName, \
MacroComponentName + CString ( "." ) + MacroClassName, \
functionName, \
Data ) ;

#else

#pragma message ( "Compiling without Data Logger" )

#define PUT_MSG( errorName, functionName, Data )
#endif


*** file: logging.h
#include <string>
void put_msg(const std::string &errorName, const std::string
&functionName, const std::string &Data);

*** file: log_on.cpp
void put_msg(const std::string &errorName, const std::string
&functionName, const std::string &Data)
{
// implement function here
}

*** file: log_off.cpp
void put_msg(const std::string &errorName, const std::string
&functionName, const std::string &Data)
{
// do nothing
}

Now you link against the file containing the logging function you want.
You can even provide other, new logging functions without modifying
existing code.

Conditional compilation is one of those things that you can't do without
macros. But you should be very careful with it, because it can lead to
code that is horribly ugly and difficult to understand. I think your
example is a mostly acceptable use - it's much better than littering
your code with things like this:

void func()
{

#ifdef DATALOGGER_ACTIVE
write_log(/* whatever */);
#endif

// ...
}

It gets even worse when you need two different sections of code - one
for when the logger is active and one for when it's inactive. It gets
worse still if there are a lot of these conditionally compiled sections,
or if the sections are long. If you really need multiple configurations
which are that different, it's probably best to encapsulate the
functionality somehow and provide multiple implementations that do the
right thing for each configuration.

-Kevin
--
My email address is valid, but changes periodically.
To contact me please use the address from a recent posting.

Jul 19 '05 #6
Joe Simon escribió:
This macro PUT_MSG is used throughout the code to provide a multi leveldata
loggin mechanism to monitor the application during runtime. It is
controllable on an individual compilation unit level, so as a level
completes dubugging and test you can set DATALOGGER_ACTIVE to false andall
of the code associated with the logging calls get removed from the
application.
How would I accomplish this without mcaros ?


Use a inline function instead. And if you want to avoid even the macro
used for the ifdef you can use a const varaible and an if on it, and the
optimizer will take care that not code is generated when not needed.

Regards.
Jul 19 '05 #7

"Michael Winter" <M.Winter@[no-spam]blueyonder.co.uk> wrote in message
news:Wz*********************@news-text.cableinet.net...
In a recent post ("About C error" by Victor, 21 Sep 2003), comments were
made about the poster's use of macros. What I would like to know is why
they are considered bad? I'm not referring to their use as 'functions'; I
realise the loss of type-safety and the possible evaluation errors that can occur. However, what would be the harm with numeric and text literals?
Those have types too.
Consider a number that plays a significant role in the implementation of an algorithm, and in that implementation the number is required in two, or
more, different scopes. There wouldn't be much point in declaring a
const-qualified variable in both scopes as it spoils a benefit of
identifying such 'magic' numbers - defining it in a single, easily locatable position (for maintenance).


You would just declare a single const that is accessible in both scopes,
just like you'd declare a single macro that was accessible to both pieces of
source code.
Jul 19 '05 #8
Joe Simon <jb******@lmco.com> wrote in message
news:bk*********@cui1.lmms.lmco.com...

[snip]
This macro PUT_MSG is used throughout the code to provide a multi level data loggin mechanism to monitor the application during runtime. It is
controllable on an individual compilation unit level, so as a level
completes dubugging and test you can set DATALOGGER_ACTIVE to false and all of the code associated with the logging calls get removed from the
application.
How would I accomplish this without mcaros ?


You've already received a non-macro alternative from Kevin Goodsell, but I
just wanted to point out that the OP's question was confined to numerical
and text literals, which is the context in which I responded. I don't claim
that there is never an occasion when you need a macro.

DW

Jul 19 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

699
by: mike420 | last post by:
I think everyone who used Python will agree that its syntax is the best thing going for it. It is very readable and easy for everyone to learn. But, Python does not a have very good macro...
4
by: Tech Witch | last post by:
We have a cluster set up at my office ( Active/Active ) that has been pitched as some prime real-estate, apparently, as the best place in the office for a database. Now it looks like one of my...
7
by: Clinton Pierce | last post by:
I'm calling a method in another assembly that's supposed to return a string, and possibly that string might be empty. The code looks something like this: string d = r.Field("date").ToString();...
2
by: Martin Høst Normark | last post by:
Hi everyone Has anyone got the least experience in integrating the Digital Signature with an ASP.NET Web Application? Here in Denmark, as I supose in many other countries, they're promoting...
8
by: CDARS | last post by:
Hi all, I have a confusing question on ASP.NET cookies usage: 1> Response.Cookies("test").value = Now 2> Response.Write(Request.Cookies("test").value) 3> 4> Response.write("<hr>") 5>...
34
by: davehowey | last post by:
I have a problem. I'm writing a simulation program with a number of mechanical components represented as objects. When I create instances of objects, I need to reference (link) each object to the...
9
by: raghav4web | last post by:
I use a select box with a fix width (via stylesheet). So some of the entries are cut on the right side if they're too long. Is there a way to display them complete like a tool tip on a mouseover? ...
2
by: beary | last post by:
I have a page with a form which has automatically generated fields, (which come from mysql column names). There could be any number of these fields, and I have no way of knowing exactly what they're...
1
by: Jim in Arizona | last post by:
I've been searching a lot for a simple example to search for a single account name in active directory but have been unable to find what I'm looking for. I did find an exmple (that worked) that...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.