Can I redefine a macro with another #define directive?

Viewed 603

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.

2 Answers

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.

Related