C macro argument 'storage' - c

Given:
#define f(x, y) (x+y)
#define g(x, y) (x*y)
#define A 1, 2
#define B 2, 3
int main() {
int a = f(A);
int b = g(A);
int c = f(B);
int d = g(B);
}
which does not work,
how can I make it work? The basic idea is that I have one list of arguments that I want to pass to two different macros, without repeating the list of long arguments every time.
Is there a way to do this? [You're welcome to modify f & g; you're even welcome to modify A & the way I call the macros. The only requirements are:
1) the arguemnt list can only appear once
2) it can't be hard coded ... so that I can call the macros with different arguments
If you're solution doesn't quite work but 'almost works' (for you definition of almost), I'd like to hear it too, perhaps I can fudge it to work.
Thanks!
Edit: f & g must be macros. They capture the symbol names and manipulate them.

You could do this:
static int f(int x, int y) { return (x+y); }
static int g(int x, int y) { return (x*y); }
#define A 1, 2
#define B 2, 3
If you were using a C compiler that supported a nonstandard inline directive, you could eliminate the overhead of a function call. And if you were using C++,
template<T> T f(T x, T y) { return (x+y); }
template<T> t g(T x, T y) { return (x*y); }
#define A 1, 2
#define B 2, 3
which would work roughly the same as your intended C macro solution.
If f and g must be macros, there isn't any way with the C preprocessor to pass multiple arguments to the macros without an actual comma appearing at the invocation site. In order to do that, you would have to add a pre-preprocessor level above the C preprocessor.

If you were using C99, you can use the compound initialiser syntax to do this by passing multiple arguments as a single array:
#define f(a) (a[0]+a[1])
#define g(a) (a[0]*a[1])
#define A ((int[]) {1, 2})
#define B ((int[]) {2, 3})
GCC supports this compound literal syntax in both C89 and C++ mode.

EDIT: A version that works with unmodified A and B
#define f(x, y) (x+y)
#define g(x, y) (x*y)
#define A 1, 2
#define B 2, 3
#define APPLY2(a, b) a b
#define APPLY(a, b) APPLY2(a, (b))
int main(int argc, char* argv[])
{
int x= APPLY(f, A);
int y= APPLY(f, B);
int z= APPLY(g, A);
int d= APPLY(g, B);
return 0;
}

Maybe this is what you want:
#include<iostream>
using namespace std;
#define A 1, 2
template <typename T>
inline T f(T a, T b) { return a + b; }
int main()
{
cout << f(A) << endl;
return 0;
}

Related

Using Macros in a program that calculates the midrange of three values

I am trying to create a program that uses macros for determining the mid-range for three values. The midrange is defined as:
midrange(a, b, c) = (min(a, b, c) + max(a, b, c)) / 2
For example:
midrange(3, 10, 1) = (min(3, 10, 1) + max(3, 10, 1)) / 2
= (1 + 10) / 2
= 11 / 2
= 5.5
I am still new to programming, and I am not sure if the syntax I am using for macro definitions is correct. My first question is, can I define a macro in the main function? My second question, should I use curly braces, normal parenthesis, or nothing at all for the body of the macro, that is, the replacement list?
This is what my program looks like for calculating the midrange of three integer values:
#include <stdio.h>
#define MIN(A, B) {(A) < (B) ? (A) : (B);}
#define MAX(A, B) {(A) > (B) ? (A) : (B);}
int main(){
//scans the three values
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
int min = MIN(MIN(a, b), c);
int max = MAX(MAX(a, b), c);
//defines new macro for calculating the midrange
//is this allowed/correct formatting and syntax?
#define MIDRANGE((min + max) / 2);
/* initializes variable mrange to equal to the value returned
function-like macro, MIDRANGE */
double mrange = MIDRANGE((min + max) / 2);
printf("The mid-range is: %lf", mrange);
return 0;
}
The reason why I declared the variable mrange as a double is because I want the value of the MIDRANGE macro to be precise, meaning that it will keep the decimal places after the division by 2 in the equation.
Any help is appreciated:)
You can declare a macro anywhere in the code, but unless you have a very specific reason to restrict its usage to a function, it typically appears in the beginning of the .c file or in a .h file.
Macros work by substitution. So if you have something similar to the following:
#define MIN(A, B) {(A) < (B) ? (A) : (B);}
int main(void)
{
int min = MIN(MIN(a, b), c);
}
It will be preprocessed into:
int min = {({(a) < (b) ? (a) : (b);}) < (c) ? ({(a) < (b) ? (a) : (b);}) : (c);};
You can see this by yourself, if you are using GCC, with the command gcc -E source.c. This is obviously not what you wanted, and it will give you a compilation error.
We never use ; at the end of macros, neither put them in blocks. To avoid unexpected operator association with complicated expressions, we guard macro parameters and the whole macro within parentheses.
Your MIN macro should look somewhat like this:
#define MIN(A, B) ((A) < (B) ? (A) : (B))
Finally, there are two things going on with your MIDRANGE macro. First, it should be taking arguments, like you did with MIN. Ideally, it should take three arguments; after all, the whole reason to make it a macro is so that the macro user won't have to calculate everything. Second, if you want the result to be a floating-point number, you should divide by 2.0, not 2.
Here's my first suggestion:
#define MIDRANGE(A, B, C) ((MIN(MIN(A, B), C) + MAX(MAX(A, B), C)) / 2.0)
However, why is this a macro? Make it a function. It's more readable, and easier to mantain. So here's my second suggestion:
double midrange(int a, int b, int c)
{
int min = MIN(MIN(a, b), c);
int max = MAX(MAX(a, b), c);
return (min + max) / 2.0;
}
regarding:
#define MIN(A, B) {(A) < (B) ? (A) : (B);}
#define MAX(A, B) {(A) > (B) ? (A) : (B);}
Lets remember that a macro is nothing more than a direct text replacement.
So looking at:
int min = MIN(MIN(a, b), c);
results in:
int min = { {(a) < (b) ? (a) : (b);} < (c);};
as is obvious from the above,
min is outside the braces '{' and '}' so will be difficult to assign to
the resulting statement contains two spurious ';' characters, which is what the compiler is complaining about
Suggest:
#define MIN( A, B ) ((A) < (B)) ? (A) : (B)
Similar considerations exist for the MAX macro

How to control C Macro Precedence

#define VAL1CHK 20
#define NUM 1
#define JOIN(A,B,C) A##B##C
int x = JOIN(VAL,NUM,CHK);
With above code my expectation was
int x = 20;
But i get compilation error as macro expands to
int x = VALNUMCHK; // Which is undefined
How to make it so that NUM is replaced first and the JOIN is used?
You can redirect the JOIN operation to another macro, which then does the actual pasting, in order to enforce expansion of its arguments:
#define VAL1CHK 20
#define NUM 1
#define JOIN1(A, B, C) A##B##C
#define JOIN(A, B, C) JOIN1(A, B, C)
int x = JOIN(VAL,NUM,CHK);
This technique is often used with the pasting and stringification operators in macros.

When can the parentheses around arguments in macros be omitted?

Often and often I felt some of the parentheses around arguments in macro definitions were redundant. It’s too inconvenient to parenthesize everything. If I can guarantee the argument needs not be parenthesized, can I omit the parentheses? Or is parenthesizing them all highly recommended?
I came up with this question when I wrote:
#define SWAP_REAL(a, b, temp) do{double temp = a; a = b; b= temp;}while(0)
I think that if an argument appears as an l-value in the macro, the parentheses can be omitted because that means the argument appears with no other operation.
My reasoning is:
The associative priority of assignment symbols is merely higher than comma’s.
You cannot confuse the compiler into thinking that your argument is an expression with a comma in it. For example, SWAP(a, b, b) will not be interpreted successfully as
do{double temp = a, b; a, b = b; b= temp;}while(0)
which can pass compilation.
Am I right? Can anyone give me a counter-example?
In the following example,
#define ADD(a, b) (a += (b))
I think the argument a needn’t be parenthesized. And in this specific case, neither needs the argument b, right?
#JaredPar:
#include <stdio.h>
#define ADD(a, b) (a += (b))
int main(){
int a = 0, b = 1;
ADD(a; b, 2);
return 0;
}
This cannot be compiled successfully on my VS2010. Error C2143: syntax error : missing ')' before ';'
In a nutshell, you don’t need to parenthesize the arguments having appeared as an l-value in the macro, but you are highly recommended to parenthesize them all.
Rules of Macros:
DO NOT make macros with side effects!
As for macros with no side effect, just parenthesize all the arguments without second thought!
As for macros with side effect, stop being obsessive! Parenthesize them all! TnT
Here is one case where it makes a demonstrable difference
ADD(x;y, 42)
With parens this leads to a compilation error but without it leads to code that compiles.
(x;y) += 42; // With parens errors
x;y += 42; // Without parens compiles
This may look like a silly example but it's possible combining macros together can easily lead to strange code expressions like the above.
Why take the chance here? It's just 2 characters
It's unsafe to omit if you use any operator that isn't lowest precedence in your expression. I believe that would be comma.
a op b where op is some operator like +, * etc. will always bind wrong if a contains an expression of low precedence like 1 || 2.
Note I'm not claiming it's safe in those cases. There are more creative ways to break macros. By the way, don't use macros with side effects in the first place. More generally, don't use macros as functions. (See, e.g., Effective C++).
There are macros where you're concatenating elements to make a string (perhaps using the # operator), or building identifiers out of macro arguments using the ## operator. In such cases, you don't parenthesize the arguments.
Also, I think that when the macro arguments are themselves passed as function arguments, then you don't absolutely have to parenthesize them:
#define CALLOC(s, n) calloc(s, n)
You can play fiendish games calling such a macro (CALLOC({3, 4})), but you get what you deserve (a compilation error) — I'm not aware of a way of calling that macro that would work if instead of the macro you wrote the same arguments as a direct call to calloc().
However, if you are using the arguments in most arithmetic expressions, then you do need to wrap them in parentheses:
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
Obviously, if you invoke it with arguments with side effects, then you get what you get. But the arguments won't be misinterpreted as they could be if you wrote:
#define MIN(x, y) x < y ? x : y
and then invoked it as:
MIN(x = 3 * y + 1, y = 2 * x - 2);
The comment by Moon suggests a SWAP_INT macro.
The following code using that macro compiles cleanly when compiled using default options, but fails to compile with -DWITH_PARENTHESES set.
#include <stdio.h>
#ifdef WITH_PARENTHESES
#define SWAP_INT(a, b) do { int temp = (a); (a) = (b); (b) = temp; } while (0)
#else
#define SWAP_INT(a, b) do { int temp = a; a = b; b = temp; } while (0)
#endif
int main(void)
{
int p = 319;
int q = 9923;
int x = 23;
int y = 300;
printf("p = %8d, q = %8d, x = %8d, y = %8d\n", p, q, x, y);
SWAP_INT(p, q); // OK both ways
SWAP_INT(x, y); // OK both ways
printf("p = %8d, q = %8d, x = %8d, y = %8d\n", p, q, x, y);
SWAP_INT(x /= y, p *= q); // Compiles without parentheses; fails with them
printf("p = %8d, q = %8d, x = %8d, y = %8d\n", p, q, x, y);
return 0;
}
The output:
p = 319, q = 9923, x = 23, y = 300
p = 9923, q = 319, x = 300, y = 23
p = 41150681, q = 13, x = 0, y = 3165437
That isn't a safe or effective way of swapping integers — the macro without the parentheses is not a good idea.
JFTR: when compiled without -DWITH_PARENTHESES, the line for the macro with the expressions is inscrutable:
do { int temp = x /= y; x /= y = p *= q; p *= q = temp; } while (0);
Normally, a swap macro expects two variable names — or array elements, or structure or union members, or any mix of these. It does not expect to be given arbitrary expressions. The parentheses ensure that the assignment to x /= y (which is not an lvalue) fails; without the parentheses, the expression is interpreted, but it isn't anything like what was intended (if, indeed, anything could be intended when 'swapping' two expressions like that).

What is the library for mathematical calculation in C?

How can i use square?
For example below calculation:
2^4=16
But when i do this the result is:6
Is there any library for this calculation without using multiplication?
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int c,a=2,b=4;
c=a^b;
printf("%d",c);
return 0;
}
and How i can use radical in C?
In C, ^ is the XOR operator. 2 XOR 4 does indeed equal 6.
You should include the math.h header file:
#include <math.h>
double pow( double base, double exp );
...
x = pow(2, 4);
^ in C is the XOR operator.
Use pow() for what you want to achieve, like;
c = pow(a, b);
When linking your program you might need to reference the math library, by adding the linker option -lm.
Referring the update to your question: Use sqrt():
double x = sqrt(4); /* Results in 2. */
Or simply use:
... = pow(4, 1./2.); /* Also results in 2. */
or
double y = pow(8, 1./3.); /* To also find 2. */
In general this formular applies:
Programmatical this can be done by:
/* Return n-th radical root of the m-th power to x. */
double nrt_mpow(doubel x, double m, double n)
{
return pow(x, m/n);
}
/* Return n-th radical root of x. */
double nrt(double x, root n)
{
return nrt_mpow(x, 1, n):
}
Or alternativly implemented as macros:
#define NRT_MPOW(x, m, n) pow((x), (m)/(n))
#define NRT(x, n) NRT_MPOW((x), 1., (n))
The header to the math library is:
#include <math.h>
And instead of ^, C uses pow().
c = pow(a,b);
The operator ^ is not power in C language. You should use pow(a,b).
There is a header file math.h. You can use numerous mathematical function which are written there.
pow() function of math.h is the tool you want for exponentiation.

XOR Swapping output prediction

#include <stdio.h>
void fun(char a[]){
a[0]^=a[1]^=a[0]^=a[1];
}
int main(int argc, char **argv){
char b[10];
b[0]='h';
b[1]='j';
fun(b);
printf("%c",b[0]);
return 0;
}
What is wrong with this code. It shall swap the b[0] and b[1] but it is not swapping.
Undefined behavior for a[0]^=a[1]^=a[0]^=a[1];. Order of evaluation and assignment is not defined.
The "The New C Standard. An Economic and Cultural Commentary" book gives two variants of xor-swap at page 1104:
Example
1 #define SWAP(x, y) (x=(x ^ y), y=(x ^ y), x=(x ^ y))
2 #define UNDEFINED_SWAP(x, y) (x ^= y ^= x ^= y)
/* Requires right to left evaluation. */
So, the second variant is not portable and is incorrect.

Resources