What does #define, EQ(a, b) ((a) == (b)) mean? - c

I have this been given C code where the heading statement includes the following:
#define, EQ(a, b) ((a) == (b))
What does it mean?

The comma is an error that will prevent the code from compiling: I'll assume that it's a typo.
Given:
#define EQ(a, b) ((a) == (b))
This defines a macro for the equality operator ==.
Using this macro later in the code, you can type, e.g.:
if (EQ(2+2, 4))
instead of:
if (2+2 == 4)
Not very useful, really.

It means nothing: this code is ill-formed. The token immediately following a #define must be an identifier, which , is not.
If the , were to be removed, this would define a function-like macro named EQ that takes two arguments.

Let's take it step by step
#define MAX 10
This will replace every instance of the word "MAX" by 10 in your code file. this is very much like defining a constant variable with one major difference. The interpretation of #define statement is done way before compilation. which helps for an example to use MAX as an array size. Which would have caused a compiler error in many cases if you have used a variable instead.
you can use cpp <filename.c> command in Linux terminal to see what will happen when a macro is executed.
for an example this code:
#define MAX 10
int numbers[MAX];
after preprocessing (i.e. interpretation of the preprocessor macros)
int numbers[10];
note that the #define statement will vanish once interpreted.
This takes us to another example
#define square(x) (x * x)
every instance of square(x) in our code will not only be replaced by (x * x) but also the value of x will be replaced. Which has an effect similar to function deceleration but again it is different
so
square(5) will be replaced by (5 * 5)
Finally our example
#define, EQ(a, b) ((a) == (b))
This will replace every instance of EQ(a, b) by ((a) == (b))
so for an example
EQ(4, 5) will be replaced by ((4) == (5))
Now what does "==" mean? it is the "check if equal" if 4 and 5 are equal the whole expression would evaluate as 1 (which obviously is not true) and thus this expression will end up to be evaluated as 0.
Which more or less like the effect of this function
int EQ(int a, int b)
{
return (a == b);
}
Which could be also written as
int EQ(int a, int b)
{
if (a ==b) return 1;
if (a !=b) return 0;
}
Note that with the macro we avoided two variable declarations and there is no function call really and it is in general quicker. This advantage will be obvious if you have a slower processor (or microprocessor).
Finally let me state the obvious
#define simple_macro 5
int some_integer_variable = 10;
.
.
.
some_integer_variable = simple_macro;
simple_macro = 12; /* illegal statement */
simple_macro++; /* illegal statement */
because after running the preprocessor this will be
int some_integer_variable = 10;
.
.
.
some_integer_variable = 5;
5 = 12;
5 ++;
Oh! I might have talked too much but let me leave you with this (obvious) code
#define MAX 10
int variable = MAX; /*this is a MAX variable */
char some_string[] = "the MAX value"; /* no replacement will happen here */
int variable_MAX; /* no replacement will happen here */
after running the preprocessor will be
int variable = 10;
char some_string[] = "the MAX value";
int variable_MAX;

Related

Get the value of a macro using a string with macro name

I have a set of macro definitions that the name only change on the number between "C_" and "_E". What I need is a macro that gets a integer variable and returns the integer value of the corresponding macro definition in case it exists, if it does not exist, it returns "-1" or gives a compile error. Is that possible? The code I need is something like this:
#include <stdio.h>
#define C_1_E 4
#define C_2_E 2
#define C_3_E 0
#define C_4_E 420
#define STR(x) #x
#define STR_MACRO(x) "C_" STR(x) "_E"
#define MACRO_VAL(x) ... // return the value of the macro C_x_E when x=1,2,3 or 4
void main() {
uint8_t n;
for(n=1;n<=4;n++) printf("val %u: %u\n",n, MACRO_VAL(STR_MACRO(n)));
}
Expected output:
val 1: 4
val 2: 2
val 3: 0
val 4: 420
According to my search, this is not possible, but I can swear I did cross this solution once, but I didn't need it back then although I thought it could be helpful.
If you need to have a macro specifically, not a function, then it must be that a macro that expands to a function call is not acceptable either. That makes sense to me only if you need the conversion of macro number to macro expansion to be performed at compile time, by the preprocessor. That doesn't appear to be a necessity for the example code, but there are cases where it would indeed be needed.
And that's too bad, because the C preprocessor then provides no way to achieve what you ask. Variables do not exist or have values at compile time, so there is no way at compile time for the compiler to convert a variable name to the value it represents, much less to build a macro name out of it, much less to expand such a name to its replacement text.
You could, however, do it with numeric literals instead of a variable:
#define EXPAND(x) x
#define MACRO_VAL(n) EXPAND(C_ ## n ## _E)
printf("val %d: %d\n",n, 1, MACRO_VAL(1));
printf("val %d: %d\n",n, 2, MACRO_VAL(2));
printf("val %d: %d\n",n, 3, MACRO_VAL(3));
printf("val %d: %d\n",n, 4, MACRO_VAL(4));
If you try to expand that with an argument that does not produce the name of a defined macro or in-scope variable then that (almost surely) will produce a compile-time error for a reference to an undefined variable.
If run-time evaluation were acceptable after all, then you could write a function that does it (which you could wrap in a macro if you wanted):
#define MACRO_VAL(n) lookup_macro(n)
#define EXPAND(x) x
#define MACRO_CASE(i) case i: return EXPAND(C_ ## i ## _E)
int lookup_macro(int n) {
switch (n) {
MACRO_CASE(1);
MACRO_CASE(2);
MACRO_CASE(3);
MACRO_CASE(4);
default: return -1;
}
}
That will return -1 for an arithmetic argument that is not covered by the defined cases.
You could also consider a lookup table, possibly wrapped in a function, but that would require somewhat more code to provide a -1 result in the event of an argument that doesn't match any macro, especially if the macro numbers are not all consecutive or if the least of them is not known in advance.
Token pasting approaches are inappropriate as x is a variable name.
Here is a simplistic approach that will work as long as the macro argument is an expression without side effects:
#include <stdio.h>
#define C_1_E 4
#define C_2_E 2
#define C_3_E 0
#define C_4_E 420
// return the value of the macro C_x_E when x=1,2,3 or 4
#define MACRO_VAL(x) ((x) == 1 ? C_1_E : \
(x) == 2 ? C_2_E : \
(x) == 3 ? C_3_E : \
(x) == 4 ? C_4_E : -1)
int main() {
int n;
for (n = 1; n <= 4; n++)
printf("val %u: %u\n", n, MACRO_VAL(n));
return 0;
}

Check max value from three variables by using preprocessor in C

I want to print the value of the variable, which has the highest value. I want to do this by using the preprocessor, but I don't know how to do this. It's easy to do this by using if-else, but how to do that by using preprocessor?
This is my code
#include <stdio.h>
#define MAX(a,b,c)
#if a > (b && c)
# define a
#endif
#if b > (a && c)
# define b
#else
# define c
#endif
int main (void)
{
int wynik;
int a = 6;
int b = 13;
int c = 9;
wynik = MAX(a,b,c);
printf("%i", wynik);
return 0;
}
And this is the errors from my terminal
E:\skrypty_c>gcc -o Cwiczenie12_4.exe Cwiczenie12_4.c
Cwiczenie12_4.c: In function 'main':
Cwiczenie12_4.c:17:11: error: expected identifier or '(' before '=' token
int c = 9;
^
Cwiczenie12_4.c:18:23: error: expected expression before ';' token
wynik = MAX(a,b,c);
That's not how it works. Your max-of-three macro would be something like
#define MAX(a, b, c) ((a) <= (b)? (b) <= (c)? (c) : (b) : (a) <= (c)? (c) : (a))
but frankly, it would be much better as a function:
inline int max(int a, int b, int c) {
if(a <= b) {
if(b <= c) return c;
return b;
}
return a <= c? c : a;
}
Preprocessor cannot be used for that. Preprocessor does not know anything about the c variables and sysntax.
You cant use any preprocesor conditional expressions in the #defines.
if you want to use macro to find max of 3 tokens you need to use C expressions for that as it will be evaluated runtime (or compile time), not during the preprocessing
#define MAX(a,b,c) (a) > (b) ? ((a) > (c) ? (a) : ((c) > (b) ? c : (b))) : ((b) > (c) ? (b) : (c))
You cannot check the value of runtime variables through preprocessor conditionals. They can check only the values of preprocessor level symbols. For example
#define A 5
#if (A > 3)
...
#endif
Looking at the way you used #define and #if, my guess is that you meant defining some sort of preprocessor level function having #define a similar role of def func (): in Python. That's not how it works.
#define A expr just replaces the symbol A with expression expr in the current source file before compilation. No occurrences of A, no substitutions
#define A(b,c) expr is like the previous one, but uses b,c like function parameters, and they are expanded in the replaced in expression expr using the values passed when the macro is called.
#if expr or #ifdef symbol or #ifndef symbol are ways to check the value or even the simple definition of symbols previously defined through #defines (or through compiler option -D) in order perform conditional compilation of whole sections of code. These sections are closed with #endif, and alternative sections in case of false conditions can be compiled using #else and #elif directives.
What you can do, and I suspect it was your actual purpose, is to define a macro finding the maximum value among its parameters:
#define MAX(a,b,c) \
(((a>b) && (a>c))? a : ((b>a) && (b>c))? b : c ))
I used ternary operator to calculate the max value.
Note: the \ character allows to place a macro on multiple lines. It needs to be the last character of the line.

macro arguments

What will the program print when the inputs are 2,3?
#include <stdio.h>
#define min(a,b) ((a) > (b) ? (b) : (a))
#define inc(a) a++
#define mult(a,b) (a * b)
int main(void) {
int x = 1, y = 2;
scanf("%d %d",&x,&y);
printf("min(%d,inc(%d))",x,y);
printf("=%d\n",min(x,inc(y)));
printf("min(mult(%d,%d+2),11)",x,y);
printf("=%d\n",min(mult(x,y+2),11));
return 0;
}
edit: I get funny answer for negative numbers i.e -1,-2.
Why is inc(-2) change y to zero instead of -1?
Think of a macro as simply string replacement. Just replace the macro name and parentheses with the body of the macro definition, replacing the macro parameters with what is passed in. An example is easier:
#define hello(a) a+a
...
int y = hello(x);
Would be replaced with:
int y = x+x;
To answer your question, do this manually, and very, very carefully. For nested macros, start with the inside one. Did I mention do this carefully? Don't add or remove any sets of parentheses.
The output would be:
min(2,inc(3))=2
min(mult(2,4+2),11)=11
What do you mean with overwrite?
If you define a function like you did above and call for example this:
inc(x);
.. then the compiler turns it into x++. The variable a is just a name for the "paramter" and will also be replaced by the real variable.
What operating system are you running? you can easily run this yourself and see the results
if your on Windows I would suggest getting CodeBlocks or Visual Studios
if your on Linux or MAC , learn to compile from terminal using gcc or g++

Can the ternary operator be expanded into if–else statements in C macros?

Define a macro MAX3 that gives the maximum of three values.
This is what I came up with:
#define MAX3(a,b,c) ( ((a) > (b)) && ((a) > (c)) ) ? (a) : ((b) > (c)) ? (b) : (c)
This is hard to read. Is there a way to write an equivalent macro with if–else statements?
Having an expression-like macro with statements inside is not possible in standard C99 language (because in C99 statements and expressions are deeply different, both syntactically and semantically).
However, GCC (and some other compilers with extensions inspired by GCC, e.g. clang) provides a nice extension for that : statement expressions (the documentation gives an example related to your question). With that extension you could code something like
#define MAX3(A,B,C) ({ int a=(A); int b=(B); int c=(C); int m; \
if (a>b) m=a; else m=b; \
if (c>m) m=c; \
m; }) /* bad macro */
however that still won't work if you use that macro like e.g.
int badex(int x, int y) {
int a= x+y; int m= x*y; int d=x-y;
return MAX3(a,m,d);
}
I hope you see why it won't work (name clashes e.g. between the a inside badex and the a inside MAX3 macro). So you need a way to have unique names at every invocation of your macro. Again, GCC provides a nice extension for that, the __COUNTER__ macro (expanded to a unique number, counting) used with concatenation in the preprocessor.
Then you'll code something like
#define MAX3(A,B,C) MAX3_COUNTED((A),(B),(C),__COUNTER__)
#define MAX3_COUNTED(A,B,C,N) ({ \
int a_##N=(A); int b_##N=(B); int c_##N=(C); \
int m_##N; \
if (a_##N>b_##N) m_##N = a_##N; else m_#N = b_##N; \
if (c_##N>m_##N) m_##N=c_##N; \
m_##N; }) /* better example */
Then the first invocation of our macro e.g. MAX3(i++,j++,k++) might expand to MAX3_COUNTED((i++),(j++),(k++),1) which gets expanded into something using a_1 b_1 ... and the second invocation, e.g. MAX3(a,m,d) expanded as MAX3_COUNTED((a),(m),(d),2) would use a_2 b_2 etc so is better.
And of course, defining a static inline max3(int a, int b, int c) function is cleaner (in particular because of side effects: your MAX3 macro gives naughty effects and results with a call like MAX3(i++,j++,k++) etc)
The general lesson about this is that you should when possible avoid macro (preferring inline functions), and when you absolutely need macros take care about name clashes and expansions.
Using GCC invoked as gcc -C -E shows you the preprocessed form of your program.
It's probably better to do it this way:
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MAX3(a, b, c) MAX(a, MAX(b, c))
Or better still, use an inline function rather than resorting to old skool preprocesser abuse:
inline int max3(int a, int, int c) { return max(a, max(b, c)); }
It's a lot more robust than a macro and just as efficient.

macro with arguments

Let's say I define macro with arguments, then invoke it as follows:
#define MIN(x,y) ((x)<(y)?(x):(y))
int x=1,y=2,z;
z=MIN(y,x);
Given that (a) macro works as text substitution, (b) that actual args here are like formal args, only swapped, -- will this specfic z=MIN(y,x) work as expected ? If it will, why ?
I mean, how preprocessor manages not to confuse actual and formal args ?
This question is about technicalities of C compiler. This is not c++ question.
This question does not recommend anybody to use macros.
This question is not about programming style.
The internal representation of the macro will be something like this, where spaces indicate token boundaries, and #1 and #2 are magic internal-use-only tokens indicating where parameters are to be substituted:
MIN( #1 , #2 ) --> ( ( #1 ) < ( #2 ) ? ( #1 ) : ( #2 ) )
-- that is to say, the preprocessor doesn't make use of the names of macro parameters internally (except to implement the rules about redefinitions). So it doesn't matter that the formal parameter names are the same as the actual arguments.
What can cause problems is when the macro body makes use of an identifier that isn't a formal parameter name, but that identifier also appears in the expansion of a formal parameter. For instance, if you rewrote your MIN macro using the GNU extensions that let you avoid evaluating arguments twice...
#define MIN(x, y) ({ \
__typeof__(x) a = (x); \
__typeof__(y) b = (y); \
a < b ? a : b; \
})
and then you tried to use it like this:
int minint(int b, int a) { return MIN(b, a); }
the macro expansion would look like this:
int minint(int b, int a)
{
return ({
__typeof__(b) a = (b);
__typeof__(a) b = (a);
a < b ? a : b;
});
}
and the function would always return its first argument, whether or not it was smaller. C has no way to avoid this problem in the general case, but a convention that many people use is to always put an underscore at the end of the name of each local variable defined inside a macro, and never put underscores at the ends of any other identifiers. (Contrast the behavior of Scheme's hygienic macros, which are guaranteed to not have this problem. Common Lisp makes you worry about it yourself, but at least there you have gensym to help out.)
It will work as expected.
#define MIN(x, y) ((x) < (y) ? (x) : (y))
int x=1,y=2,z;
z = MIN(y, x);
becomes
int x=1,y=2,z;
z = ((y) < (x) ? (y) : (x));
Does the above have any syntactic or semantic errors? No. Therefore, the result will be as expected.
Since you're missing a close ')', I don't think it will work.
Edit:
Now that's fixed, it should work just fine. It won't be confused by x and y any more than it would be if you has a string x with "x" in it.
First off, this isn't about the C compiler, this is about the C Pre-processor. A macro works much like a function, just though text substitution. What variable names you use make no impact on the outcome of the macro substitution. You could have done:
#define MIN(x,y) ((x)<(y)?(x):(y))
int blarg=1,bloort=2,z;
z=MIN(bloort,blarg);
and get the same result.
As a side node, the min() macro is a perfect example of what can go wrong when using macros, as an exercise you should see what happens when you run the following code:
int x,y,z;
x=1;y=3;
z = min(++x,y);
printf("%d %d %d\n", x,y,z); /* we would expect to get 2 3 2, but we get 3 3 3 . */

Resources