Using a ternary operator inside of a preprocessor - c

I've just started learning C and I need some help with understanding macrocommands. I wanted to create one which calculates the maximum between two numbers.
I know the names are not chosen quite well, but it is just for testing purposes.
Here's the code:
#include <stdio.h>
#define max(a, b) (int max2, a>=b ? max2 = a : max2 = b)
void main()
{
int a, b;
scanf("%d%d", &a, &b);
int maximum = max(a, b);
printf("%d", maximum);
}
I'm getting an error on line 8, (the one with int maximum = max(a, b) ) saying "expected a ')'".
I guess that's because I'm using the preprocessor wrong (in my opinion), but I don't know how I should do it properly in this case.
Can anybody help me understand what am I doing wrong and how I should use preprocessors? Thanks.

I don't think you understand how a macro works; you don't declare a new variable max2 inside it. The preprocessor is a simple text substitution system.
Your macro expands to:
int maximum = (int max2, a>=b ? max2 = a : max2 = b);
This is a syntax error. A max macro is very simple, all you need is:
#define max(a, b) ((a) >= (b)) ? (a) : (b)
This will then expand to:
int maximum = ((a) >= (b)) ? (a) : (b);
Which will give you the result you want.

What you have written, comes down to:
int maximum = (int max2, a>=b ? max2 = a : max2 = b); // this looks weird (what's that max2 for?)
Why don't you simply write the following:
#define max(a, b) ((a)>=(b) ? (a) : (b))
Like this, your line of code becomes:
int maximum = ((a)>=(b) ? (a) : (b));
Which looks a lot more logical. (Briefly, you don't need max2)

Related

Abstracting operators by booleans

Lets say I have a boolean bool, and two ints a and b. If bool is true, I want to return a < b, and if bool is false I want to return a > b. Obviously I can write:
if (bool)
return a < b;
else
return a > b;
But this is repetitive. I only want to have to write one return statement, of the form return a (desired operator) b, but I am not sure what that would look like. What would be the simplest way to do this? Obviously this example is fairly trivial, but for larger blocks of code, I'd prefer to not have to rewrite it multiple times with only the operator changed.
In my opinion there's no such operator in C, plus, C doesn't have operator overloading, so that's not possible too.
The best you can do is a function to encapsulate this logic:
function findWhetherLessOrMore(bool findWhetherLess, int operand1, int operand2) {
return findWhetherLess ? operand1 < operand2 : operand1 > operand2;
}
You can change the function name to be concise, so that it does not bloat the code when used a large number of times.
As said in other answers here, I would suggest reconsidering your design if you've to do too much of these condition checks in the program.
There are a handful of options, but none of them are simpler than just writing directly what you want.
Macros:
#define OVERLOADER(cond,a,b,op1,op2) cond ? a op1 b : a op2 b
usage:
return OVERLOADER(cond, a, b, <, >);
Virtual functions (which may optimise well when defined static)
typedef int(*func)(int a, int b);
static int lt(int a, int b) { return a < b; }
static int gt(int a, int b) { return a > b; }
static int dispatcher(int cond, int a, int b, func aa, func bb) {
return cond ? aa(a,b) : bb(a,b);
}
// usage:
int main(int ac, char **av) {
return dispatcher(ac, (int)av[0][0],(int)av[0][1], lt, gt);
}
Also if the operator is particularly difficult to evaluate, one might convert the problem into the form
if (!cond) {
swap(a,b);
}
return a < b;
The ternary operator will always help in writing conditional statements in a single line and/or having a single return statement.
return cond ? a < b : a > b;
// or
return (cond ? a : b) < (cond ? b : a);
I would anyway be a bit suspicious of the need to have a block of hundreds of conditions like this, which my intuition tells that should have a better higher level design.

C Programming - #define function [duplicate]

This question already has answers here:
Preprocessor macro in C
(3 answers)
Closed 5 years ago.
I am learning C in depth. But I am not getting this program. Somebody, please tell me how the output of the below program is m=2, n=3
#include <stdio.h>
#define MAX(a,b) a>b ? a:b
int main()
{
int m,n;
m=3+MAX(2,3);
n=2*MAX(3,2);
printf("m=%d, n=%d\n",m,n);
return 0;
}
This is why parenthesis in macro definitions are important.
A macro does simple text substitution. So when you do this:
m=3+MAX(2,3);
It expands to this:
m=3+2>3 ? 2:3
With the implicit parenthesis:
m = ((3+2)>3) ? 2:3
Which is probably not what you want.
You need to put parenthesis around the entire macro as well as around each argument wherever it is used:
#define MAX(a,b) ((a)>(b) ? (a) : (b))
This will then expand to:
m = 3 + ((2)>(3) ? (2):(3))
Also note that with a macro like this you open yourself up to side effects of one of the operands. For example, if you did this:
int a=2, b=3;
m = MAX(a++,b);
You would get:
int a=2, b=3;
m = ((a++) > (b) ? (a++) : (b));
This invokes undefined behavior because it attempts to modify a more than once in an expression without a sequence point.
This is what happens in your case:
int main() {
int m,n;
m=3+2>3 ? 2:3; //(3+2)>3 ? 2 : 3 = 2
n=2*3>2 ? 3:2; //(2*3)>2 ? 3 : 2 = 3
printf("m=%d, n=%d\n",m,n);
return 0;
}
If you rewrite your defined to #define MAX(a,b) ((a)>(b) ? (a):(b))
then you will have desired output as it will be evaluated to:
//Correct way with parenthesis
int main() {
int m,n;
m=3+((2)>(3) ? (2):(3)); //6
n=2*((3)>(2) ? (3):(2)); //6
printf("m=%d, n=%d\n",m,n);
return 0;
}

Shorthand Way of Conditional Assignments

Is there a shorthand way of writing equivalent code to:
if (variable > max){
variable = max;
}else if (variable < -max){
variable = -max;
}
I know I can use ternary operators to get code like this:
variable = variable > max ? max : variable;
variable = variable < -max ? -max : variable;
Question:
But is there an even shorter version of this code?
Note: Not nested ternary operators, either.
P.S.: This isn't necessarily a language-specific question, but I'm writing my code in C so I'd like to have answers that can work in that language.
You could probably use this construct:
if (abs(variable) > max) {
variable = sgn(variable) * max;
}
There is no sgn(x) function in standard C library, but it is easy enough to implement it using arithmetic operations:
#define sgn(x) (((x) > 0) - ((x) < 0))
Here is an working example:
#include <stdio.h>
#include <math.h>
#define sgn(x) (((x) > 0) - ((x) < 0))
int main(void)
{
int variable = -100, max = 20;
if (abs(variable) > max) {
variable = sgn(variable) * max;
}
printf("%d\n", variable);
return 0;
}
Note, that it will not work for INT_MIN on systems, that use two's complement representation, because -INT_MIN cannot be represented as int (kudos for #M.M).
You can nest conditional operators:
variable = variable > max ? max : (variable < -max ? -max : variable);
IMHO this is almost unreadable, so I don't recommend it.

Why the analyzation of code isn't right?

Why the output is "0 -6" and not "4 60"? Isn't k=8, l=2?
#define MAC(a,b) (a<b ? a*b:a-b)
void main (void)
{
int i=2;
int j=4;
int k=MAC(i,j);
int l=MAC(j,i);
i=MAC(k+l,k-l);
j=MAC(k-l,k+l);
printf("%d %d\n", i,j);
}
One immediate problem. The expression
MAC(k+l,k-l)
becomes
(k+l<k-l ? k+l*k-l:k+l-k-l)
^^^^^^^
and, as you can see from the underlined bit, the expression is not what you think it is due to the precedence rules (multiplication is done before addition).
This can be fixed by ensuring each argument in the macro is parenthesised:
#define MAC(a,b) ((a)<(b) ? (a)*(b):(a)-(b))
but that still won't help if you pass in something like n++ as it will be incremented multiple times.
Macros are very simple text substitutions and are well known to cause problems such as what you're seeing. My advice would be to turn MAC into a proper function that will avoid the problem completely, something like:
int mac (int a, int b) {
if (a < b)
return a * b;
return a - b;
}
#define MAC(a,b) (a<b ? a*b:a-b)
void main (void)
{
int i=2;
int j=4;
int k= i<j ? i*j:i-j;
int l= j<i ? j*i:j-i;
i= k+l<k-l ? k+l*k-l:k+l-k-l;
j= k-l<k+l ? k-l*k+l:k-l-k+l;
printf("%d %d\n", i,j);
}
This is what was produced after your code got preprocessed. preprocess macro happens before compilation. unlike compilation, there is no symbolic linking of variables that have occurred, but a mere 1 to 1 replacement of what you have defined.

Smallest of three numbers using macro MINIMUM3

I have to create a code that determines the smallest of three numeric values.
Macro MINIMUM3 should use macro MINIMUM2 (the difference btwn two numeric values) to determine the smallest number. the input values come from the user input. I am not very familiar with using macros and my textbook doesn't really help in showing me an example of how they can work together to carry out their function. The code below is the work in progress that I have so far but I am running into errors on lines 3, 13, 16, and 20.
#define MINIMUM2 (a,b) (a < b ? a:b)
#define MINIMUM3 (a,b,c) (MINIMUM2(a,b) c? MINIMUM (a,b) :c)
int main (void) {
int x,y,z;
int temp;
printf("Please enter three numbers\n");
scanf("%d%d%d, &x&y&z);
temp = MIN(x,y,z);
printf("The smallest number entered is:\n");
printf("%d", &temp);
getchar ();
return0;
}
You have a couple of issues in your code:
MINIMUM3 uses MINIMUM instead of MINIMUM2
The logic of MINIMUM3 is broken
You need to remove spaces after macro names
You are missing a closing double quote and commas in call of scanf
You are using MIN in place of MINUMUM3
You are passing an address of temp to printf
Here is how you can fix this:
#define MINIMUM2(a,b) (a < b ? a:b)
#define MINIMUM3(a,b,c) (MINIMUM2(MINIMUM2(a,b),c))
int main (void) {
int x,y,z;
int temp;
printf("Please enter three numbers\n");
scanf("%d%d%d", &x, &y, &z);
temp = MINIMUM3(x, y, z);
printf("The smallest number entered is:\n");
printf("%d", temp);
getchar ();
return0;
}
Demo.
You can improve your macros by enclosing each parameter in parentheses:
#define MINIMUM2 (a,b) ((a) < (b) ? (a) : (b))
Your definition of the MINIMUM3 macro will lead to a syntax error. You should try something like
#define MINIMUM3(a, b, c) MINIMUM2(MINIMUM2(a, b), c)
or
#define MINIMUM3(a, b, c) MINIMUM2(a, MINIMUM2(b, c))
Also make sure to call MINIMUM3 in main, not MIN.

Resources