What happens if I redefine a macro in C without un

2019-07-24 22:15发布

问题:

This question already has an answer here:

  • #define many times without #undef,is it legal? 4 answers
  • What happens when a C preprocessor macro is defined twice? 3 answers

I want to know the severity of the warning that my compiler is throwing for the "macro MACRO_NAME redefined". It is redefined in the header file without undef directive like below:

#define MACRO_NAME 3.14
/*other macro definition*/
#define MACRO_NAME 8192

What value does MACRO_NAME take throughout the program? Does it depend on the compiler? Is #undef mandatory here?

回答1:

Well the second macro #define MACRO_NAME 8192 is taken into account . Anyhow it is a bad practiced because this can cause huge confusion when the new developer reads whole code written by you .

Usually it may happen that the same macro defined with different values in different header files , at that time it depends in what order you include these two header file . See in this case it may be easy for you but it is highly confusing when the new developer takes over your code.

Generally, treat all warnings as errors. Then you don't have to worry about what value the macro would have.(taken from comment above)

I will not recommend practice to redefine macro without undef

Usually you get this warning, and should use always a #undef as such a redifinition is invalid according to the C89 standard:

Well a beautiful example has been presented:

int a;
#define VAL 100
a=VAL; // a is 100 here
#define VAL 200
a=VAL; // a is 200 here

You can see the problem :)



回答2:

If it compiles, then it overwrites the first macro with the value of the second.

#include <stdio.h>

#define MACRO_NAME 3.14
/*other macro definition*/
#define MACRO_NAME 8192

int main()
{
    printf("%d", MACRO_NAME);

    return 0;
}

Output: 8192

Usually you get this warning, and should use always a #undef as such a redifinition is invalid according to the C89 standard:

5:0: warning: "MACRO_NAME" redefined

3:0: note: this is the location of the previous definition

Verified by cpp.sh, onlinegdb.com and tutorialspoint.com.



回答3:

What you are doing is invalid:

The C11 standard states this:

6.10.3 Macro replacement
Constraints
...
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.

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.

In the case of

#define MACRO_NAME 3.14

#define MACRO_NAME 8192

the replacement lists are not identical.



回答4:

From C Standard#6.10.3p2 [emphasis mine]

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.

So, this is not valid as per the standard because the replacements (3.14 and 8192) are not identical:

#define MACRO_NAME 3.14
/*other macro definition*/
#define MACRO_NAME 8192

You can use #undef to make this code valid, like this:

#define MACRO_NAME 3.14
 // the part of code using MACRO_NAME before #undef will expanded to 3.14
#undef MACRO_NAME

/*other macro definition*/
#define MACRO_NAME 8192
 // after this the code using MACRO_NAME expanded to 8192

From C Standard#6.10.3.5p1 (Scope of macro definitions) [emphasis added]

1 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. Macro definitions have no significance after translation phase 4.


Additional:

From C Standard#6.10.3.5p8, the macro redefinition rules demonstration:

8 EXAMPLE 6 To demonstrate the redefinition rules, the following sequence is valid.

     #define      OBJ_LIKE      (1-1)
     #define      OBJ_LIKE      /* white space */ (1-1) /* other */
     #define      FUNC_LIKE(a)   ( a )
     #define      FUNC_LIKE( a )( /* note the white space */ \
                                   a /* other stuff on this line
                                       */ )

But the following redefinitions are invalid:

     #define      OBJ_LIKE    (0)     // different token sequence
     #define      OBJ_LIKE    (1 - 1) // different white space
     #define      FUNC_LIKE(b) ( a ) // different parameter usage
     #define      FUNC_LIKE(b) ( b ) // different parameter spelling