Conflict of macros and functions in C

What error occurs when a conflict of macros and functions occurs in C? Is this a macro processor error or is this error due to any language violation?

For example, in this code:

#include <stdio.h> #define MAX(i, j) (i>j)? i : j int MAX(int i, int j){ return (i>j) ? i : j; } int main(){ int max = MAX(5, 7); printf("%d",max); return 0; } 

The program throws a compile time error. But I don’t understand if it was a language violation or a macro extension error or something else.

+4
source share
6 answers

At the pre-processing stage, the code is converted to:

 int (int i>int j)? int i : int j{ return (i>j) ? i : j; } int main(){ int max = (5>7)? 5 : 7; printf("%d",max); return 0; } 

... which anyone can say is illegal code C.

(With gcc you can use the -E option to view a pre-processed version of the file.)

+11
source

Others pointed to the problem, but did not give any solutions. It would be best to use MAX as a built-in function. If the macro is in the header, place the inline function definition in the header instead. If you still want to use a macro (or using an old C compiler that does not support built-in functions), you can define a function as follows:

 int (MAX)(int i, int j){ return (i>j) ? i : j; } 

This will prevent the alarming expansion of macros and provide MAX as an external function. This will allow you, for example, to assign your address to a variable.

 extern int (MAX)(int, int); ... int (*max_func_ptr)(int, int); ... max_func_ptr = MAX; 
+3
source

You will get a compiler error, because the macro will be expanded before the compilation attempt is made.

This is a really nasty problem, and one for which there really is no solution. For this reason, you should avoid defining non-function macros as much as possible, especially in headers that are widely included. Like everyone else, they have their own place, but you must be careful not to abuse them.

+2
source

There is no error that occurs specifically to cause a conflict. What happens is that macro processing is performed first, so namespaces are not taken into account in the definition of macros - this is one of the main reasons macros are considered bad and should be avoided except as a last resort. See this question for an example of a situation where someone completely correctly using the BitTest name for a template was screwed up because someone decided to create a macro using this name for the β€œalias” of another name: Win32: BitTest, BitTestAndComplement, .. . <- How to disable this garbage?

So, in your example, as the other answers were mentioned, after the preprocessing step has occurred, you will get something like the following fragment passed to the C compiler instead of defining your function:

 int (int i>int j)? int i : int j{ return (i>j) ? i : j; } 

This is not valid C, so you get a compiler error that might say (from GCC 3.4.5):

 error: syntax error before "int" 

or (from MSVC 9):

 error C2059: syntax error : 'type' 

Which really doesn't help much, because when you look at the line referenced by the error in your editor, it will look like this:

 int MAX(int i, int j){ 

which looks valid.

There are several methods that help you avoid the problem:

  • use all caps for macro names and only macro names; it’s an agreement that is mostly followed to keep the macro namespace separate from the names used for other things.

  • puts parsers around names that you don’t want to expand as macros (this only works for function type macros). If your example was written as follows:

     int (MAX)(int i, int j){ return (i>j) ? i : j; } 

    this would not expand the macro. However, I do not see people doing this very often. One set of utility routines that I use uses this technique to protect against macro name conflicts, and I often ask questions about why all function names are in parens. Also, several editors are confused with the navigation function for these files.

  • avoid using macros; as I said, this is one of the reasons that macros are considered bad. There are other reasons, including that they can easily lead to the fact that the extended form will create bad or unexpected expressions if you use parsers incorrectly around macro parameters or evaluate a macro parameter that has side effects more than once.

    Instead, use built-in functions or function templates.

+2
source

Since preprocessor macros are used only for processing plain text, these conflicts always cause a compile-time error.

+1
source

Pre-processing is done first, so line 4 will be as follows:

 int (int i>int j)? int i : int j 

which is unacceptable. C.

+1
source

Source: https://habr.com/ru/post/1301825/


All Articles