tags:

views:

139

answers:

3

If I use the macro:

#define AND

in the following way:

if(...)
{
...
}
elseANDif(...)
{
...
}

What output does the preprocessor produce?

Edit: I intend to use:

#define TEST(params) if(...){...}else  

the ... in if(...) is a complicated expression using params

the ... in {...} performs some operations & is independent of params

#define AND

TEST(x1) AND TEST(x2)
{
    //the code for the final else
}

Is the AND helping here or can I do without it?

+9  A: 

No, this isn't going to work as you expect. And you can test what the preprocessor does by running your code through cpp.

eliben@eliben-desktop:~/temp$ cat z.c
#define AND

if(...)
{
    ...
}
elseANDif(...)
{
    ...
}

eliben@eliben-desktop:~/temp$ cpp z.c
# 1 "z.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "z.c"


if(...)
{
    ...
}
elseANDif(...)
{
    ...
}

The technical reason is that when cpp expands macros it looks for a complete identifier token matching this macro's name. I.e. in your case, it looks for the identifier AND. However when it parses the code it doesn't find such an identifier. It finds elseANDif which is quite a different identifier. It has no way to break elseANDif into constituents, and that's a good thing because otherwise macros would work very badly. Imagine:

const int FUSIONDEBUG = 5;

Whatever that means, in real C code this would break awfully, since NDEBUG is almost always defined in production code to be empty (google on what NDEBUG means).


Regarding your edit, the best advice I can give you on such matters is DON'T DO IT. (ab)Using macros like this may appear at first to make the code more readable, but in the long term it makes it much less readable, with the added peril that macros are tricky to get perfectly right and with certain combination of tokens can blow up on you badly.

So you can definitely do without the AND as well as without the TEST altogether.

Eli Bendersky
i have a piece of code which checks whether a file has been successfully opened or not, based on which it either prints the error message or moves on to the actual file-io in the else part. Sometimes 2 files have to be opened, hence I have added an else to the previous macro. Any suggestions you can provide in getting this macro running would be appreciated.
Kedar Soparkar
@crypto: I'll be glad to help but your need is still unclear to me from the comment. Since this is quite a different issue now, I suggest you open a separate SO question with an appropriate name and a detailed description of your requirements in the body of the question.
Eli Bendersky
Eli's advice is right on. While it is seductive to use macros to tune the C language, that way is a path to madness. Just don't do it. On the other hand, it can on rare occasion make sense to use macros as a substitute for inline functions.
RBerteig
Secure
+2  A: 

This:

#define TEST(condn) if(...){...}else

is nonsense; what do you expect the ellipses (...) to do!?

the example usage you gave would expand to

if(...){...} else if(...){...}else
{
    //the code for the final else
}

which is patently nonsense; where is the condn argument used?. Either way whatever you really intended the AND has no effect other than dummy readability. If you are trying to invent a new language, the C preprocessor is not the way to do this. I can see no advantage to what you appear to be trying to achieve over more straightforward code.

If you intended:

 #define TEST(condn) if(condn){/*some code*/}else

then how is the resultant:

if(a==b){/*some code*/} else if(b==c){/*some code*/}else
{
    //the code for the final else
}

better than:

if(a==b || b==c)
{
    /*some code*/
} 
else
{
    //the code for the final else
}

where /*some code*/ is not unnecessarily duplicated?

Note that here the single condition chained by || is equivalent to your multiple conditions chained by else if, so even if you use the TEST macro, there is no need to use it that way when:

TEST( a==b || b==c)
{
    //the code for the final else
}

will suffice.

Macros are often ill-advised at the best of times, but you have chosen a particularly prime example of macro abuse! Consider for example how you might debug such code in a source-level debugger.

Clifford
@Clifford, I agree with your point, but do you honestly believe I have ellipsis(...) in my if code?
Kedar Soparkar
Please read the edit now, I have modified it to properly portray what I am doing.
Kedar Soparkar
@crypto: Of course not, but why post it that way!? It just creates ambiguity unnecessarily. It may also have been an incorrect attempt at a variadic macro. The edit does not help clarify much. If you can't show what you are doing, there is little point is posting it at all.
Clifford
+1  A: 

The short answer to your question is "yes". You can certainly do what you are suggesting. Here is a basic, working example:

#include <stdio.h>

#define AND
#define TEST(params) if (!params) { printf(#params " was false\n"); } else 

int main(int argc, char ** argv)
{
    int param_1 = 1;
    int param_2 = 0;

    TEST(param_1) AND TEST(param_2)
    {
        printf("success!\n");
    }
}

After macro expansion, the code would essentially look like this:

int main(int argc, char ** argv)
{
    int param_1 = 1;
    int param_2 = 0;

    if (!param_1) { printf("param_1 was false\n"); } else 
    if (!param_2) { printf("param_2 was false\n"); } else
    {
        printf("success!\n");
    }
}

As pointed out by others, doing something like this is questionable because it messes with the way people read code and can make future debugging difficult. In a case such as this, I would definitely recommend using a function call if at all possible. This is the approach that Secure recommends in his comment:

int test_parameters(int params)
{
    if (!params) { printf("bad parameters"); return 0; }
    else { return 1; }
}

int main(int argc, char ** argv)
{
    int param_1 = 1;
    int param_2 = 0;

    if (test_parameters(param_1) && test_parameters(param_2))
    {
        printf("success!\n");
    }
}
e.James