Legitimate use-case for macro redefinition - c

Reading a chapter on the preprocessor, it stated that redefinition of macros is allowed only if the redefinition matches the previous definition, i.e:
#define FOO 0
#define BAR 1+1
#define FOO 0 /* ok. */
#define BAR 1 + 1 /* not ok */
I'm baffled by this.
Granted that this behavior is actually correct (the book might be wrong, of course), my question is: Why allow this? I can't think of any legitimate use-cases where this might be used (granted I don't have the experience), is there a rational behind it?

The idea is to make preprocessor to actively watch repetitive definitions and ensure that they remain identical.
The rationale behind this rule is actually mentioned in the Rationale to C99 standard
The Committee desired to disallow “pernicious redefinitions” such as
(in header1.h)
#define NBUFS 10
(in header2.h)
#define NBUFS 12
which are clearly invitations to serious bugs in a program. There remained, however, the question of “benign redefinitions,” such as
(in header1.h)
#define NULL_DEV /* the first time */ 0
(in header2.h)
#define NULL_DEV /* the second time */ 0
The C89 Committee concluded that safe programming practice is better served by allowing benign redefinition where the definitions are the same. This allows independent headers to specify their understanding of the proper value for a symbol of interest to each, with diagnostics generated only if the definitions differ.
Basically, the idea is to deliberately catch and expose situations when two definitions exist and they are different. If users were always forced to anticipate and #undef the previous definition before defining their own, they would quietly override what was not intended to be overridden, without a way to ensure consistency.
By deliberately supplying an extra identical definition you effectively introduce an extra level of protection: if someone modifies the previous definition, the preprocessor will immediately catch and report the resulting mismatch.
In other words by defining
#define A 42
in your code you are not only defining A as 42, you are also telling the preprocessor that you want to ensure that everyone else (in this translation unit) shares the same idea of what A should be.

Your book is strictly correct but perhaps fails to point out - or you might overlooked it -
that you may redefine a previously defined preprocessor with no diagnostic provided
that you undefine it before you redefine it. E.g:
#define FOO 0
#define BAR 1+1
#define FOO 0 /* ok. */
#undef BAR
#define BAR 1 + 1 /* ok */
If you attempt to redefine a macro while it is defined there's a high probability
you're committing a blunder and would be grateful for the preprocessor to
draw that to your attention.
When you define a macro in a file that inhabits a large, complex
product codebase - which perhaps has multiple, intertwined build-configurations
controlled by macros that are ultimately defined outside the codebase,
in the build system - then it may be beyond your unaided wits to know that
your definition will never, disastrously, contradict a prior definition in building any
configuration. You'd want to know that, and the preprocessor will tell you.
On the other hand, there are circumstances where you want say: FOO may or
may not have got a prior definition from somewhere at the point where my
file is compiled. Regardless, I want it to have my definition now.
I know what I'm doing and on my head be it. The preprocessor lets you assume that
responsibility as in:
foo.c
#include <bar.h>
...
#undef FOO // I don't care what it previously might have been.
#define FOO what I want here
and keeps quiet.
In that light, the question of why the preprocessor does not complain of
a macro redefinition that doesn't differ from the last one is probably
dispelled. Identical redefinitions are harmless. Useless, yes, but not
necessarily implying that you, or anyone, has repeated themselves. Library
header files libfoo.h and libbar.h might both be included in baz.c and
each of them might contain.
#define MAX_HANDLES 255
which the preprocessor will see twice. But it's harmless, so why complain?

Related

Incompatible redefinition of macro

When I compile my c project with make command, there is the error
Error: #47-D: incompatible redefinition of macro "MACRO_NAME"
It looks like MACRO_NAME is already defined in one of the header files, but I want to redefine or hardcode new value for MACRO_NAME.
How to remove this error?
There is no clean way to define this macro so that it realiably and predictably is not used in the meaning of one of the definitions, when the other one is meant.
If you use a mechanism with undef, then you run the risk to undefine the other meaning, define it to your meaning and then end up with code which expects the other meaning seeing and using your meaning.
The only way to achieve reliability and predictability is to make sure that code which expects one meaning does not include (neither directly nor indirectly) the header which defines the other meaning.
You can do so by
a) defining in a way that neither definition can be done when the other one is already defined. To do so, in both cases
#ifdef MACRO_NAME
#error Separation of the two meanings of MACRO_NAME failed!
/* the other definition of MACRO_NAME is alreay visible */
#endif
#define MACRO_NAME MyMeaning
b) make sure that no code includes both definitions
Actually a) is only a technical help to make sure b). If you say that you will not ever include both definitions into one code file, then you have no problem. In that case, you do not get the #error from a). In that case you do not have a problem with using the wrong definition. Good. How do you know? How can you be sure that you do not have the problem, even if you change code, even if your colleague changes code? Use a), then you will be clearly told when you get caught by the redefinition trap. If you use #undef instead, then you have not prevented the problem, just hidden it and made it harder to debug.
c) in the case that you can only influence one of the two definitions, i.e. the other one is by another supplier, the best way is to change the name of your own definition. Whatever effort that causes in your code, it will be less than getting caught be unintended redefinition problems.
d) in the case that you cannot influence any of the two definitions (which is of course NOT the case you are asking about) you have to separate the code files into two groups, those who use one definition and not the other and the group which uses the other definition and only that one.
Use #undef to redefine MACRO in the header file when it is needed
#ifdef MACRO_NAME
#undef MACRO_NAME
#endif
#define MACRO_NAME 100

Is there a tool that checks what predefined macros a C file depends on?

To avoid impossible situation one could reduce the problem to two cases.
Case 1
The first (simplest) case is situation where the preprocessor has a chance to detect it, that is there's a preprocessor directive that depends on a macro being predefined (that is defined before the first line of input) or not. For example:
#ifdef FOO
#define BAR 42
#else
#define BAR 43
#endif
depends on FOO being predefined or not. However the file
#undef FOO
#ifdef FOO
#define BAR 42
#endif
does not. A harder case would be to detect if the dependency actually does matter, which it doesn't in the above cases (as neither FOO or BAR affects the output).
Case 2
The second (harder) case is where successful compilation depends on predefined macros:
INLINE int fubar(void) {
return 42;
}
which is perfectly fine as far as the preprocessor is concerned whether or not ENTRY_POINT is predefined, but unless INLINE is carefully defined that code won't compile. Similarily we could in this case it might be possible to exclude cases where the output isn't affected, but I can't find an example of that. The complication here is that in the example:
int fubar(void) {
return 42;
}
the fubar being predefined can alter the successful compilation of this, so one would probably need to restrict it to cases where a symbol need to be predefined in order to compile successfully.
I guess such a tool would be something similar to a preprocessor (and C parser in the second case). The question is if there is such a tool? Or is there a tool that only handles the first case? Or none at all?
In C everything can be (re)defined, so there is no way to know in advance what is intended to be (re)defined. Usually some naming conventions helps us to figure out what is meant to be a macro (like upper-case). Therefore it is not possible to have such tool. Of course if you assume that the compilation errors are caused by missing macro definitions then you can use them to analyze what is missing.

Is #define banned in industry standards?

I am a first year computer science student and my professor said #define is banned in the industry standards along with #if, #ifdef, #else, and a few other preprocessor directives. He used the word "banned" because of unexpected behaviour.
Is this accurate? If so why?
Are there, in fact, any standards which prohibit the use of these directives?
First I've heard of it.
No; #define and so on are widely used. Sometimes too widely used, but definitely used. There are places where the C standard mandates the use of macros — you can't avoid those easily. For example, §7.5 Errors <errno.h> says:
The macros are
EDOM
EILSEQ
ERANGE
which expand to integer constant expressions with type int, distinct positive values, and which are suitable for use in #if preprocessing directives; …
Given this, it is clear that not all industry standards prohibit the use of the C preprocessor macro directives. However, there are 'best practices' or 'coding guidelines' standards from various organizations that prescribe limits on the use of the C preprocessor, though none ban its use completely — it is an innate part of C and cannot be wholly avoided. Often, these standards are for people working in safety-critical areas.
One standard you could check the MISRA C (2012) standard; that tends to proscribe things, but even that recognizes that #define et al are sometimes needed (section 8.20, rules 20.1 through 20.14 cover the C preprocessor).
The NASA GSFC (Goddard Space Flight Center) C Coding Standards simply say:
Macros should be used only when necessary. Overuse of macros can make code harder to read and maintain because the code no longer reads or behaves like standard C.
The discussion after that introductory statement illustrates the acceptable use of function macros.
The CERT C Coding Standard has a number of guidelines about the use of the preprocessor, and implies that you should minimize the use of the preprocessor, but does not ban its use.
Stroustrup would like to make the preprocessor irrelevant in C++, but that hasn't happened yet. As Peter notes, some C++ standards, such as the JSF AV C++ Coding Standards (Joint Strike Fighter, Air Vehicle) from circa 2005, dictate minimal use of the C preprocessor. Essentially, the JSF AV C++ rules restrict it to #include and the #ifndef XYZ_H / #define XYZ_H / … / #endif dance that prevents multiple inclusions of a single header. C++ has some options that are not available in C — notably, better support for typed constants that can then be used in places where C does not allow them to be used. See also static const vs #define vs enum for a discussion of the issues there.
It is a good idea to minimize the use of the preprocessor — it is often abused at least as much as it is used (see the Boost preprocessor 'library' for illustrations of how far you can go with the C preprocessor).
Summary
The preprocessor is an integral part of C and #define and #if etc cannot be wholly avoided. The statement by the professor in the question is not generally valid: #define is banned in the industry standards along with #if, #ifdef, #else, and a few other macros is an over-statement at best, but might be supportable with explicit reference to specific industry standards (but the standards in question do not include ISO/IEC 9899:2011 — the C standard).
Note that David Hammen has provided information about one specific C coding standard — the JPL C Coding Standard — that prohibits a lot of things that many people use in C, including limiting the use of of the C preprocessor (and limiting the use of dynamic memory allocation, and prohibiting recursion — read it to see why, and decide whether those reasons are relevant to you).
No, use of macros is not banned.
In fact, use of #include guards in header files is one common technique that is often mandatory and encouraged by accepted coding guidelines. Some folks claim that #pragma once is an alternative to that, but the problem is that #pragma once - by definition, since pragmas are a hook provided by the standard for compiler-specific extensions - is non-standard, even if it is supported by a number of compilers.
That said, there are a number of industry guidelines and encouraged practices that actively discourage all usage of macros other than #include guards because of the problems macros introduce (not respecting scope, etc). In C++ development, use of macros is frowned upon even more strongly than in C development.
Discouraging use of something is not the same as banning it, since it is still possible to legitimately use it - for example, by documenting a justification.
Some coding standards may discourage or even forbid the use of #define to create function-like macros that take arguments, like
#define SQR(x) ((x)*(x))
because a) such macros are not type-safe, and b) somebody will inevitably write SQR(x++), which is bad juju.
Some standards may discourage or ban the use of #ifdefs for conditional compilation. For example, the following code uses conditional compilation to properly print out a size_t value. For C99 and later, you use the %zu conversion specifier; for C89 and earlier, you use %lu and cast the value to unsigned long:
#if __STDC_VERSION__ >= 199901L
# define SIZE_T_CAST
# define SIZE_T_FMT "%zu"
#else
# define SIZE_T_CAST (unsigned long)
# define SIZE_T_FMT "%lu"
#endif
...
printf( "sizeof foo = " SIZE_T_FMT "\n", SIZE_T_CAST sizeof foo );
Some standards may mandate that instead of doing this, you implement the module twice, once for C89 and earlier, once for C99 and later:
/* C89 version */
printf( "sizeof foo = %lu\n", (unsigned long) sizeof foo );
/* C99 version */
printf( "sizeof foo = %zu\n", sizeof foo );
and then let Make (or Ant, or whatever build tool you're using) deal with compiling and linking the correct version. For this example that would be ridiculous overkill, but I've seen code that was an untraceable rat's nest of #ifdefs that should have had that conditional code factored out into separate files.
However, I am not aware of any company or industry group that has banned the use of preprocessor statements outright.
Macros can not be "banned". The statement is nonsense. Literally.
For example, section 7.5 Errors <errno.h> of the C Standard requires the use of macros:
1 The header <errno.h> defines several macros, all relating to the reporting of error conditions.
2 The macros are
EDOM
EILSEQ
ERANGE
which expand to integer constant expressions with type int, distinct
positive values, and which are suitable for use in #if preprocessing
directives; and
errno
which expands to a modifiable lvalue that has type int and thread
local storage duration, the value of which is set to a positive error
number by several library functions. If a macro definition is
suppressed in order to access an actual object, or a program defines
an identifier with the name errno, the behavior is undefined.
So, not only are macros a required part of C, in some cases not using them results in undefined behavior.
No, #define is not banned. Misuse of #define, however, may be frowned upon.
For instance, you may use
#define DEBUG
in your code so that later on, you can designate parts of your code for conditional compilation using #ifdef DEBUG, for debug purposes only. I don't think anyone in his right mind would want to ban something like this. Macros defined using #define are also used extensively in portable programs, to enable/disable compilation of platform-specific code.
However, if you are using something like
#define PI 3.141592653589793
your teacher may rightfully point out that it is much better to declare PI as a constant with the appropriate type, e.g.,
const double PI = 3.141592653589793;
as it allows the compiler to do type checking when PI is used.
Similarly (as mentioned by John Bode above), the use of function-like macros may be disapproved of, especially in C++ where templates can be used. So instead of
#define SQ(X) ((X)*(X))
consider using
double SQ(double X) { return X * X; }
or, in C++, better yet,
template <typename T>T SQ(T X) { return X * X; }
Once again, the idea is that by using the facilities of the language instead of the preprocessor, you allow the compiler to type check and also (possibly) generate better code.
Once you have enough coding experience, you'll know exactly when it is appropriate to use #define. Until then, I think it is a good idea for your teacher to impose certain rules and coding standards, but preferably they themselves should know, and be able to explain, the reasons. A blanket ban on #define is nonsensical.
That's completely false, macros are heavily used in C. Beginners often use them badly but that's not a reason to ban them from industry. A classic bad usage is #define succesor(n) n + 1. If you expect 2 * successor(9) to give 20, then you're wrong because that expression will be translated as 2 * 9 + 1 i.e. 19 not 20. Use parenthesis to get the expected result.
No. It is not banned. And truth to be told, it is impossible to do non-trivial multi-platform code without it.
No your professor is wrong or you misheard something.
#define is a preprocessor macro, and preprocessor macros are needed for conditional compilation and some conventions, which aren't simply built in the C language. For example, in a recent C standard, namely C99, support for booleans had been added. But it's not supported "native" by the language, but by preprocessor #defines. See this reference to stdbool.h
Macros are used pretty heavily in GNU land C, and without conditional preprocessor commands there's be no way to properly handle multiple inclusions of the same source files, so that makes them seem like essential language features to me.
Maybe your class is actually on C++, which despite many people's failure to do so, should be distinguished from C as it is a different language, and I can't speak for macros there. Or maybe the professor meant he's banning them in his class. Anyhow I'm sure the SO community would be interested in hearing which standard he's talking about, since I'm pretty sure all C standards support the use of macros.
Contrary to all of the answers to date, the use of preprocessor directives is oftentimes banned in high-reliability computing. There are two exceptions to this, the use of which are mandated in such organizations. These are the #include directive, and the use of an include guard in a header file. These kinds of bans are more likely in C++ rather than in C.
Here's but one example: 16.1.1 Use the preprocessor only for implementing include guards, and including header files with include guards.
Another example, this time for C rather than C++: JPL Institutional Coding Standard for the C Programming Language . This C coding standard doesn't go quite so far as banning the use of the preprocessor completely, but it comes close. Specifically, it says
Rule 20 (preprocessor use)
Use of the C preprocessor shall be limited to file inclusion and simple macros. [Power of Ten Rule 8].
I'm neither condoning nor decrying those standards. But to say they don't exist is ludicrous.
If you want your C code to interoperate with C++ code, you will want to declare your externally visible symbols, such as function declarations, in the extern "C" namespace. This is often done using conditional compilation:
#ifdef __cplusplus
extern "C" {
#endif
/* C header file body */
#ifdef __cplusplus
}
#endif
Look at any header file and you will see something like this:
#ifndef _FILE_NAME_H
#define _FILE_NAME_H
//Exported functions, strucs, define, ect. go here
#endif /*_FILE_NAME_H */
These define are not only allowed, but critical in nature as each time the header file is referenced in files it will be included separately. This means without the define you are redefining everything in between the guard multiple times which best case fails to compile and worse case leaves you scratching your head later why your code doesn't work the way you want it to.
The compiler will also use define as seen here with gcc that let you test for things like the version of the compiler which is very useful. I'm currently working on a project that needs to compile with avr-gcc, but we have a testing environment that we also run our code though. To prevent the avr specific files and registers from keeping our test code from running we do something like this:
#ifdef __AVR__
//avr specific code here
#endif
Using this in the production code, the complementary test code can compile without using the avr-gcc and the code above is only compiled using avr-gcc.
If you had just mentioned #define, I would have thought maybe he was alluding to its use for enumerations, which are better off using enum to avoid stupid errors such as assigning the same numerical value twice.
Note that even for this situation, it is sometimes better to use #defines than enums, for instance if you rely on numerical values exchanged with other systems and the actual values must stay the same even if you add/delete constants (for compatibility).
However, adding that #if, #ifdef, etc. should not be used either is just weird. Of course, they should probably not be abused, but in real life there are dozens of reasons to use them.
What he may have meant could be that (where appropriate), you should not hardcode behaviour in the source (which would require re-compilation to get a different behaviour), but rather use some form of run-time configuration instead.
That's the only interpretation I could think of that would make sense.

What exactly is redefinition of a macro in C? What's the point, given so many restrictions on it?

This is the first time I ran into the "redefinition of macro" concept while reading the C book by Mike Banahan (Section 7.3.2). But from what I can gauge from the following paragraph given there, redefinition won't be of any use at all other than repeating the same thing, given the tight restrictions. Of course my understanding is wrong and the author must be having a point. So can you please explain in simple terms what exactly redefinition of a macro in C is, and what exactly can we do to redefine it after we comply with the restrictions and rules given for that. A sample code will be very helpful. Thank you.
Extracted text follows:
The Standard allows either type of macro to be redefined at any time,
using another # define, provided that there isn't any attempt to
change the type of the macro and that the tokens making up both the
original definition and the redefinition are identical in number,
ordering, spelling and use of white space. In this context all white
space is considered equal, so this would be correct:
#define XXX abc/*comment*/def hij
#define XXX abc def hij
because comment is a form of white space. The token sequence for both cases (w-s stands for a white-space token) is:
# w-s define w-s XXX w-s abc w-s def w-s hij w-s
In practice, you generally do not want to redefine macros. Most of the time it happens due to name collision (two pieces of code defining a macro with the same name that may or may not do the same thing). The rule you cite says redefinition is allowed in the case where the only difference between the two definitions is white space. In that case, both definitions will do the same thing. In any other case, all bets are off.
For example, a common thing to want is the maximum of two numbers. If you write a MAX macro, one way to do it would be:
// ASSUME: multiple references to macro parameters do not cause problems
#define MAX(a, b) ((a) > (b) ? (a) : (b))
Since MAX is the obvious name for a macro that returns the maximum of two numbers, there is a pretty good chance that someone else might have the same idea and also define a MAX macro. If they happen to define it exactly the same way you did, the compiler will accept the multiple definitions, because they do the same thing (though some compilers will still warn about it).
If someone defines MAX differently, the compiler will throw an error on the redefinition. Throwing an error is a good thing. Had the compiler always picked either the first or last definitions, the programmer would most likely not be aware that a different macro than they expected will be used.
If you need to work around multiple definitions of macros (e.g., two different 3rd party libraries choose the same name), you can use #ifdef to check if the macro is already defined and #undef to "undefine" the first definition if you would rather have the second. Such solutions are generally fragile. If you have a choice, avoiding name conflicts is a better solution.

How to deal with intrusive identifiers from term.h?

Testing some code including term.h, I've seen some strange errors using usual identifiers such as tab or columns. It comes from the fact that this header defines a lot of macros. Here are some examples:
/* from term.h */
#define columns CUR Numbers[0]
#define lines CUR Numbers[2]
#define bell CUR Strings[1]
#define insert_line CUR Strings[53]
#define tab CUR Strings[134]
However, I didn't find any documentation about these macroconstants. It seems to be shortcuts to access to some members of a TERMINAL data structure. Of course, a solution is to #undef every identifier used in the source code. But it is very restrictive.
So my question is: why do not prefix the identifiers of term.h?
They are often used as local variables in real source code, so it leads to incomprehensible errors.
There are two ways to deal with the identifier clash:
Change the identifiers in term.h
Change the identifiers in your code
The first is a no-no for reasons I hopefully need not explain. term.h was there long before your code ever formed as a thought in your brain. Thus it is entirely your fault^Wproblem^Wresponsibility to have created clashing identifiers. :-)
Maybe there's another option:
Don't use/include term.h in the first place.
One option, assuming you MUST use term.h is to isolate the inclusion of that file to a particular module, so that your overall code doesn't clash. But as Jens says, it's your task to "not have name clashes". Public header files that belong to the system shouldn't be changed just because you use the same names as those.

Resources