In many places I see the usage of undefine macro before defining the same macro. For example:
#undef FORMULA
#ifdef SOMETHING
#define FORMULA 1
#else
#define FORMULA 2
#endif
What for the #undefine FORMULA used?
I may guess that it deals with the case when the macro was already defined before. But isn't the new definition overrides the old one? Thanks!
A macro name currently defined cannot be redefined with a different definition (see below), so #undef allows that macro name to be redefined with a different definition.
Here's the relevant legalese:
Both C and C++ Standards (same wording):
A macro definition lasts (independent of block structure) until a corresponding #undef directive is encountered or (if none is encountered) until the end of the preprocessing translation unit.
Slight differences in wording, same meaning:
C Standard (N1256), §6.10.3/2:
An identifier currently defined as an object-like macro shall not be redefined by another #define preprocessing directive unless the second definition is an object-like macro definition and the two replacement lists are identical. Likewise, an identifier currently defined as a function-like macro shall not be redefined by another #define preprocessing directive unless the second definition is a function-like macro definition that has the same number and spelling of parameters, and the two replacement lists are identical.
C++ Standard (N3337) §16.3/2
An identifier currently defined as an object-like macro may be redefined by another #define preprocessing directive provided that the second definition is an object-like macro definition and the two replacement lists are identical, otherwise the program is ill-formed. Likewise, an identifier currently defined as a function-like macro may be redefined by another #define preprocessing directive provided that the second definition is a function-like macro definition that has the same number and spelling of parameters, and the two replacement lists are identical, otherwise the program is ill-formed.
Same wording in both Standards:
Two replacement lists are identical if and only if the preprocessing tokens in both have the same number, ordering, spelling, and white-space separation, where all white-space separations are considered identical.
So:
#define X(y) (y+1)
#define X(z) (z+1) // ill-formed, not identical
IMHO, using #undef is generally dangerous due to the scoping rules for preprocessor macros. I'd prefer to get a warning or error from the preprocessor and come up with a different preprocessor macro rather than have some translation unit silently accept a wrong macro definition that introduces a bug into the program. Consider:
// header1.h
#undef PORT_TO_WRITE_TO
#define PORT_TO_WRITE_TO 0x400
// header2.h
#undef PORT_TO_WRITE_TO
#define PORT_TO_WRITE_TO 0x410
and have a translation unit #include both headers. No warning, probably not the intended result.
Yes, the new definition overrides all previous. But there is corresponding warning message. With #undef you have no warnings.
But isn't the new definition overrides the old one?
Yes, it does (when your compiler allows it). However, redefining a macro results in a compiler warning, which using #undefine lets you avoid.
This may be important in programming shops with strict rules on compiler warnings - for example, by requiring all production code to be compiled with -Werror flag, which treats all warnings as errors.
#undef removes the macro, so the name is free to be defined again.
If the macro was never defined in the first place, #undef has no effect, so there's no downside. #undef … #define should be read as replacing any potential previous definition, but not to imply that it must already be defined.
Popular compilers do allow you to skip the #undef, but this is not allowed by the official standard ISO C and C++ language specifications. It is not portable to do so.
Related
I have often seen code like
#ifndef HEADERFILE_H
#define HEADERFILE_H
// some declarations in
// the header file.
#endif
I want to know what #define HEADERFILE_H define HEADERFILE_H to?
I tried doing
cout<<HEADERFILE_H<<endl;
but I am getting
error: expected expression
A define preprocessing directive has the form # define identifier preprocessing-tokens, ending with a new-line character. The preprocessing-tokens is a list of zero or more preprocessing tokens. It may be empty, that is, it may have zero tokens. This means, that when the identifier is encountered in a place where macro replacement occurs, it will be replaced with nothing.1
Tests of the form #ifdef identifier, #ifndef identifier, or define identifier in a #if or #elif directive test whether identifier is defined or not. If it was not defined (or its definition was removed with the #undef directive), then the test indicates it is not defined. If it was defined, then the test indicates it was defined, even if the definition is for zero tokens.
A definition with zero tokens is different from no definition at all, and defined identifier will evaluate as true for the former and false for the latter.
Footnote
1 If the list does have tokens, then identifier will be replaced with those tokens and # and ## operators among them will be applied. A preprocessing token is largely an identifier (like foo34), a constant (like 3, 4u, or 1.8e4), one of the C operators or special characters (like * or +=), or certain other components of the C language.
It actually defines "nothing else than itself". That is: you may define a macro without assigning it a specific value. Since you can check if a given macro is defined or not, you therefore can ask for the simple "existence" of a given macro.
This is useful to indicate a context (for example, if you're compiling for a given OS) and/or the availability of some resources.
In this particular example, this is a called a "guard": it will define itself if this hasn't been done first before, as well as including the rest of the file, which is totally embedded in the #ifdef … #endif clause.
This is used to implement a kind of require_once, that is something that will be included if needed, but not multiple times. This is required when you are defining functions or declaring variables at a global scope, for instance.
This is a language idiom (I will comment it):
#ifndef HEADERFILE_H
Between this, and the last #endif everything is included in compilation, but only if HEADERFILE_H has not been defined before.
#define HEADERFILE_H
The first thing we do in the block is to #define the identifier, so next time we find this fragment again later, the contents between #ifndef and #endif will not be #included again (because of the identifier declaration).
// some declarations in
// the header file.
this block will be included only once, even if you #include this file several times.
#endif
and this marks the end of the protected block.
It is common to include some file that, indeed, #includes another, and that file includes another, leading to a point in which you don't know which files have been included and which don't. This phrasing allows you to be protected, and to be able to #include the same file several times (normally you cannot, as some definitions cannot be repeated in the same compilation unit, e.g. declarations) the lines above will include the contents and define the identifier, making next inclussions (that are effectively done) not to include the contents, as the identifier appears as #definen in second and ulterior times.
What is the motivation / rationale behind not macro-expanding arguments of #error (and #warning) directive?
The gcc documentation explicitly states:
Neither ‘#error’ nor ‘#warning’ macro-expands its argument.
P.S. For #warning (not standardized) the fix is to use #pragma message (https://stackoverflow.com/a/12638158/1778275), which (normally) macro-expands its arguments.
UPD. The question is not specifically about why gcc does not perform macro-expantion. The quote from gcc documentation is used as an example of text, which explicitly states that neither #error nor #warning macro-expands its argument. I could not find this (or similar) text in C standard. Hence, refer the quite from gcc documentation.
UPD2. In comparison with #error the #include performs macro-expantion of its arguments. Quote from the standard (ISO/IEC 9899:202x (E)):
The preprocessing tokens after include in the directive are processed just as in normal text. (Each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens.)
I don't say this is the motivation for the standard, but thinking of many of my uses of #error it would be inconvenient to have it macro-expanded.
Admittedly, my habits might have been formed by the non-expansion.
#define MINIMUMCONFIG 1
#ifndef IMPORTANTCONFIG
#error IMPORTANTCONFIG is undefined!
#error
#if IMPORTANTCONFIG < MINIMUMCONFIG
#error IMPORTANTCONFIG lower than MINIMUMCONFIG !
#endif
Shouldn't I be getting warning or error message after declaring macro in this way:
#define c 123
#define a b
#define b c
The code worked flawlessly - so just like variable definition, is macro definition stored somewhere?
This is perfectly fine, because preprocessor does not act upon macro definitions until the point of expansion. That is why the order does not matter: as long as each macro has a definition to which it could be expanded when your code makes a reference to it, the preprocessor is happy. This applies to macros that rely on other macros for their expansion.
One consequence of this behavior is that the relative order of macro declarations does not change the end result.
I know about the argument prescan when an argument is used in a C macro, but that happens when you use an already defined macro. However, when you define it, do you need to have any special care at choosing the parameter names? Does the preprocessor parse the macro in an "atomic" way so that parameter names are not expanded?
I mean, imagine this scenario:
#define MYVAL {is this safe?}
#define ADDVALUES(MYVAL,YOURVAL) do{(MYVAL)+(YOURVAL);}while(0)
int val=ADDVALUES(1,3);
How is the ADDVALUES macro parsed? Is MYVAL expanded before defining the ADDVALUES macro?
I have not read any warning about choosing the parameter names in a macro, so I tend to believe their name is not expanded before the macro is parsed (I have read warnings about naming local variables in macros, about the macros names themselves, about swallowing the semicolon, etc., but nothing about choosing the parameter names).
The scope of the parameter MYVAL is distinct from that of the object-like macro MAYVAL. Quoting from the relevant part of the Standard, 6.10.3,p10:
The parameters are specified by the optional list of identifiers,
whose scope extends from their declaration in the identifier list
until the new-line character that terminates the #define preprocessing
directive.
The last line in the example given will be expanded as
int val=do{(1)+(3);}while(0);
I tried with gcc 4.8.5
#define NV1 a
#define V1(NV1) b NV1
V1(foo)
gcc -E test.h
Result
b foo
So parameter name is not expanded as a macro and overrides the earlier conflicting definition
I want to redefine the value of a macro constant with another value. Now I know the technique of using #undef and thereafter re-#define the macro itself, like:
#define LEN_OSG 59
....
#undef LEN_OSG
#define LEN_OSG 70
I´d attempt to abbreviate this and discovered that it is possible to redefine the macro constant by just another #define directive:
#define LEN_OSG 59
....
#define LEN_OSG 70
Example program:
#include <stdio.h>
#define LEN_OSG 59
int main()
{
printf("LEN_OSG is %d.\n",LEN_OSG);
#define LEN_OSG 70
printf("LEN_OSG is %d.",LEN_OSG);
}
Of course, Both gcc and clang give me the warnings:
warning: "LEN_OSG" redefined. (gcc)
and
warning: 'LEN_OSG' macro redefined [-Wmacro-redefined] (clang)
but they do compile it (without the -Werror option of course) and give both the correct result:
Execution build compiler returned: 0
Program returned: 0
LEN_OSG is 59.
LEN_OSG is 70.
My questions:
Can I redefine a macro with another #define directive by ignoring this specific warning?
Does this in any kind involve undefined behavior or cause a potential harm to the program?
Thank you very much.
Redefining a macro (when the redefintion is not the same) is a constraint violation. The constraint is spelled out in sectino 6.10.3p2 of the C standard:
An identifier currently defined as an object-like macro shall
not be redefined by another #define preprocessing directive unless
the second definition is an object-like macro definition and
the two replacement lists are identical. Likewise, an
identifier currently defined as a function-like macro shall
not be redefined by another #define preprocessing directive
unless the second definition is a function-like macro
definition that has the same number and spelling of parameters,
and the two replacement lists are identical.
And section 4p2 states the following about constraint violations:
If a ‘‘shall’’ or ‘‘shall not’’ requirement that appears outside
of a constraint or runtime-constraint is violated, the
behavior is undefined. Undefined behavior is otherwise indicated
in this International Standard by the words ‘‘undefined
behavior’’ or by the omission of any explicit definition of
behavior. There is no difference in emphasis among these three; they
all describe ‘‘behavior that is undefined’’.
So redefining a macro invokes undefined behavior. You must use #undef if you want to redefine the macro.
You should really get used to using #undef before re-defining a macro! Most compilers will generate a warning; however, according to the C99 Standard (and also the C18 Standard - the paragraphs are the same in both):
6.10.3 Macro replacement ...
2 An identifier currently defined as an object-like macro shall not be redefined by another #define preprocessing directive unless the second definition is an object-like macro definition and the two replacement lists are identical. Likewise, an identifier currently defined as a function-like macro shall not be redefined by another #define preprocessing directive unless the second definition is a function-like macro definition that has the same number and spelling of parameters, and the two replacement lists are identical.
The 'replacement lists' for the LEN_OSG (object-like) macro in your example are 59 and then 70 - which are not identical.