C Macro Question -(x) vs (-x) - c

I'm going through quiz answers from my professor and a question was:
the correct implementation of a function like macro for absolute value is:
#define abs(x) ((x)<0 ? (-x) : (x))
#define abs(x) ((x)<0 ? -(x) : (x))
Why is the second one correct vs the first one?
And why do you have to use all the (). Like what are the rules involved? Every variable needs a ()? Thanks.

There are various related problems that the extra parentheses solve. I'll go through them one by one:
Try: int y = abs( a ) + 2
Let's assume you use:
#define abs(x) (x<0)?-x:x
...
int y = abs( a ) + 2
This expands to int y = (a<0)?-a:a+2. The +2 binds only to the false result. 2 is only added when a is positive, not when it is negative. So we need parenthesis around the whole thing:
#define abs(x) ( (x<0) ? -x : x )
Try: int y = abs(a+b);
But then we might have int y = abs(a+b) which gets expanded to int y = ( (a+b<0) ? -a+b : a+b). If a + b is negative then b is not negated when they add for the result. So we need to put the x of -x in parentheses.
#define abs(x) ( (x<0) ? -(x) : x )
Try: int y = abs(a=b);
This ought to be legal (though bad), but it expands to int y = ( (a=b<0)?-(a=b):a=b ); which tries to assign the final b to the ternary. This should not compile. (Note that it does in C++. I had to compile it with gcc instead of g++ to see it fail to compile with the "invalid lvalue in assignment" error.)
#define abs(x) ( (x<0) ? -(x) : (x) )
Try: int y = abs((a<b)?a:b);
This expands to int y = ( ((a<b)?a:b<0) ? -((a<b)?a:b) : (a<b)?a:b ), which groups the <0 with the b, not the entire ternary as intended.
#define abs(x) ( ( (x) < 0) ? -(x) : (x) )
In the end, each instance of x is prone to some grouping problem that parentheses are needed to solve.
Common problem: operator precedence
The common thread in all of these is operator precedence: if you put an operator in your abs(...) invocation that has lower precedence then something around where x is used in the macro, then it will bind incorrectly. For instance, abs(a=b) will expand to a=b<0 which is the same as a=(b<0)... that isn't what the caller meant.
The "Right Way" to Implement abs
Of course, this is the wrong way to implement abs anyways... if you don't want to use the built in functions (and you should, because they will be optimized for whatever hardware you port to), then it should be an inline template (if using C++) for the same reasons mentioned when Meyers, Sutter, et al discuss re-implementing the min and max functions. (Other answers have also mentioned it: what happens with abs(x++)?)
Off the top of my head, a reasonable implementation might be:
template<typename T> inline const T abs(T const & x)
{
return ( x<0 ) ? -x : x;
}
Here it is okay to leave off the parentheses since we know that x is a single value, not some arbitrary expansion from a macro.
Better yet, as Chris Lutz pointed out in the comments below, you can use template specialization to call the optimized versions (abs, fabs, labs) and get all the benefits of type safety, support for non-builtin types, and performance.
Test Code
#if 0
gcc $0 -g -ansi -std=c99 -o exe && ./exe
exit
#endif
#include <stdio.h>
#define abs1(x) (x<0)?-x:x
#define abs2(x) ((x<0)?-x:x)
#define abs3(x) ((x<0)?-(x):x)
#define abs4(x) ((x<0)?-(x):(x))
#define abs5(x) (((x)<0)?-(x):(x))
#define test(x) printf("//%30s=%d\n", #x, x);
#define testt(t,x) printf("//%15s%15s=%d\n", t, #x, x);
int main()
{
test(abs1( 1)+2)
test(abs1(-1)+2)
// abs1( 1)+2=3
// abs1(-1)+2=1
test(abs2( 1+2))
test(abs2(-1-2))
// abs2( 1+2)=3
// abs2(-1-2)=-1
int a,b;
//b = 1; testt("b= 1; ", abs3(a=b))
//b = -1; testt("b=-1; ", abs3(a=b))
// When compiled with -ansi -std=c99 options, this gives the errors:
//./so1a.c: In function 'main':
//./so1a.c:34: error: invalid lvalue in assignment
//./so1a.c:35: error: invalid lvalue in assignment
// Abs of the smaller of a and b. Should be one or two.
a=1; b=2; testt("a=1; b=2; ", abs4((a<b)?a:b))
a=2; b=1; testt("a=2; b=1; ", abs4((a<b)?a:b))
// abs4((a<b)?a:b)=-1
// abs4((a<b)?a:b)=1
test(abs5( 1)+2)
test(abs5(-1)+2)
test(abs5( 1+2))
test(abs5(-1-2))
b = 1; testt("b= 1; ", abs5(a=b))
b = -1; testt("b=-1; ", abs5(a=b))
a=1; b=2; testt("a=1; b=2; ", abs5((a<b)?a:b))
a=2; b=1; testt("a=2; b=1; ", abs5((a<b)?a:b))
}
Output
abs1( 1)+2=3
abs1(-1)+2=1
abs2( 1+2)=3
abs2(-1-2)=-1
a=1; b=2; abs4((a<b)?a:b)=-1
a=2; b=1; abs4((a<b)?a:b)=1
abs5( 1)+2=3
abs5(-1)+2=3
abs5( 1+2)=3
abs5(-1-2)=3
b= 1; abs5(a=b)=1
b=-1; abs5(a=b)=1
a=1; b=2; abs5((a<b)?a:b)=1
a=2; b=1; abs5((a<b)?a:b)=1

Yes, every variable needs parenthesis around it directly.
The reason is because you can pass things into the macro that aren't "nice", like arithmetic expressions or really any expression that isn't a single variable. It should be easy to see that with abs(1+2), the expanded -(1 + 2) will give a different result than (-1 + 2). This is why -(x) is more correct.
Unfortunately neither macro is safe, you should use an inline function for things like this instead. Consider:
abs (x++); // expands to ((x++) < 0 ? - (x++) : (x++))
This is clearly wrong with the macro, but it would work correctly if an inline function was used instead.
There are other problems with using macros instead of functions as well. See this question.
Edit: Noting that the question is about C, inline functions may only be available in C99.

Related

Incorrect Substitution of OpenMP Pragma in Macro Expansion

When an OpenMP pragma is used as part of an argument for a macro, it gets incorrectly substituted.
In this code:
#define make_body( ... ) { __VA_ARGS__ }
extern foo( int );
int main(){
make_body(
#pragma omp parallel for
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
)
}
I would expect that it would be expanded to:
extern foo( int )
int main(){
{
#pragma omp parallel for
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
}
}
However, (according to gcc -E) it becomes expanded to:
extern foo( int );
int main(){
#pragma omp parallel for
{
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
}
}
Is this correct behavior?
How can I get the expected behavior, preferably without changing the arguments to the macro?
Does this happen with all pragmas?
Is this an effect of the variadic macro?
Do other compilers perform the same substitution?
Using gcc (Ubuntu 5.4.0-6ubuntu1~16.04.10) 5.4.0 20160609
Is this correct behavior?
It would be most accurate to say that it is not incorrect behavior. The standard has this to say about macro arguments:
If there are sequences of preprocessing tokens within the list of arguments that would otherwise act as preprocessing directives, the behavior is undefined.
You have exercised that case, and accordingly reaped undefined behavior.
Does this happen with all pragmas? Is this an effect of the variadic macro? Do other compilers perform the same substitution?
The behavior is undefined, so it may vary among conforming implementations, and even within the same implementation, for any reason or none. I would guess that GCC is relatively consistent in this area, but in no way should you rely on that. It is not specifically tied to the macro involved being variadic.
How can I get the expected behavior, preferably without changing the arguments to the macro?
C11, which is supported by GCC 5, has a solution for the specific case of macros that emit pragmas: the _Pragma operator. It is more often used in literal macro replacement text, so that you can have a macro that represents a pragma, but it ought to work in a macro argument, too. You will, however, have to change the macro argument a bit:
make_body(
_Pragma("omp parallel for")
for( int i = 0; i < 10; i += 1 ){
foo( i );
}
)
You are not allowed to put any preprocessing directive inside the arguments to a function-like macro. (C11 6.10.3p11, last sentence.)
In this case, you should be able to write _Pragma("omp parallel for") and get the effect you want. Experimentation indicates that this works correctly with both clang and gcc (versions 7 and 8 respectively) but only if you specify -fopenmp on the command line. Yes, even if using -E.
Alternative solution this fixes a case we saw in real code which is way to big to be recreated here (not that we're exactly sure why it happens anyway).
-fopenmp is also necessary.
#define EMPTY()
#define DELAY(x) x EMPTY()
#define STRINGIZE(x) STRINGIZE_NO_PREPROCESS(x)
#define STRINGIZE_NO_PREPROCESS(x) #x
#define PRAGMA(x) _Pragma( STRINGIZE(x) )
#define DELAYED_PRAGMA_assist(x) PRAGMA(x)
#define DELAYED_PRAGMA DELAY(DELAYED_PRAGMA_assist)
#define PRAGMA_IN_MACRO_ARG(x) DELAYED_PRAGMA(x)
#define PRAGMA_IN_MACRO_BODY(x) PRAGMA(x)
PRAGMA_IN_MACRO_ARG can be used to correctly place a the pragma when the code is being passed to another macro as an argument
For example:
#define WRAP( body ) { body }
#define loop( i, N, body )\
if( N > 0 ) \
WRAP( \
PRAGMA_IN_MACRO_ARG(omp parallel for private(i)) \
for( i = 0; i < N; ++i ){ \
body \
} \
)
loop( i, 10, printf("%d\n", i); )
PRAGMA_IN_MACRO_BODY can be used to correctly place a the pragma when the code is simply part of a macro's body, and not as input to another macro
For example:
#define loop( i, N, body )\
if( N > 0 ) \
{\
PRAGMA_IN_MACRO_BODY(omp parallel for private(i)) \
for( i = 0; i < N; ++i ){ \
body \
} \
}
loop( i, 10, printf("%d\n", i); )

C macro returning type of variable

Could it be possible to create a macro function whose returned value be one of the predefined c variable data types? Something like:
#include <stdio.h>
#define IND_I_ 0
#define IND_F_ 1
#define INT_FORMAT_ "%i"
#define FLOAT_FORMAT_ "%f"
// (Of course the following macros do not make the desired jobs)
// FORMAT_ macro would be used for the variable format:
#define FORMAT_( ind_ )( (ind_) == IND_I_ ? FOR_INT_ : FOR_FLOAT_ )
// VAR_TYPE_ macro would be used for
// defining variable types and for the casting of variables:
#define VAR_TYPE_( ind_ ) ( (ind_) == IND_I_ ? int : float )
int main( void )
{
VAR_TYPE_( IND_I_ ) first_var = 123; //here I want: int first_var = 123;
VAR_TYPE_( IND_F_ ) second_var = 345.789;
//Instead of:
//printf( "int variable = " "%i" "\n", first_var );
//I would use:
printf( "int variable = " FORMAT_(IND_I_) "\n", first_var );
printf( "float variable = " FORMAT_(IND_F_) "\n", second_var );
printf( "truncated real variable = " INT_FORMAT_ "\n", (VAR_TYPE_(IND_I_))second_var );
return 0;
}
Sorry, this is not possible in the C family. (It is possible in languages with a more powerful macro system, such as Common Lisp and Rust.)
The only thing a macro can do is textual replacement. So your
#define VAR_TYPE_( ind_ ) ( (ind_) == IND_I_ ? int : float )
#define IND_I_ 0
VAR_TYPE_( IND_I_ ) first_var = 123;
expands to
( (0) == 0 ) ? int : float ) first_var = 123;
which is a syntax error. There is no way to make it evaluate that ?: expression.
There is a thing you could do that would make it work whenever the argument to VAR_TYPE_ expanded to a literal zero, one, etc.:
#define VAR_TYPE_(ind_) VAR_TYPE__(ind_)
#define VAR_TYPE__(ind_) VAR_TYPE__##ind_
typedef int VAR_TYPE__0;
typedef float VAR_TYPE__1;
// etc
... but if you're doing this at all, you probably want to allow ind_ to be an arbitrary integer constant expression and that won't work. You would get things like
VAR_TYPE_sizeof(int)==4?0:2
in the expansion and you'd be back to the syntax errors.
(Psst: Every time you put spaces on the inside of your parentheses, God kills a kitten.)
Macros r just literal replacing,so you can not do it this way.
Use c++ 11 / 14, auto type and outstream handle will fit.
The short answer is: no.
What do you want to achieve?
Why do you need flexible typing in C? Maybe you should move on to Java or Python then.
In your example, you already have type information, so using macros to substitute type-specific string literals are overkill.
If you want to control the types of the variables from the outside, which I strongly oppose, you can set up macro substitutes and inject them through a header or directly specifying them on the compiler's command line.
Example for demonstration (please don't do this at home):
#include <stdio.h>
#include <stdlib.h>
/* // eg.
#define TEH_TYPE double
#define TEH_TYPE_FMT "%f"
#define TEH_TYPE_ATO atof
*/
// Either, or see command line below.
/*
#define TEH_TYPE int
#define TEH_TYPE_FMT "%d"
#define TEH_TYPE_ATO atoi
*/
int main(int argc, char **argv) {
TEH_TYPE v;
if(argc > 1)
{
v = TEH_TYPE_ATO(argv[1]);
printf("So your thingie is " TEH_TYPE_FMT "\n", v);
}
return 0;
}
You can then compile it as gcc -DTEH_TYPE=int -DTEH_TYPE_FMT='"%d"' -DTEH_TYPE_ATO=atoi main.c -o main.
But again, please don't. I am ashamed of writing this down.

Can macro perform compound assignments

I read little gnu online docs about macro and little confused about this sentence:
Also multi-character operators such as += can be formed by token pasting
So I wander if macro can perform compound assignments,How?
#define PASTE(a,b) a##b
int foo;
foo PASTE(+,=) 2;
The only time I've ever seen this be useful was in the inner loop of a bytecode interpreter, which tends to look like a gigantic case statement with very repetitive code in each arm:
case OP_add: {
if (sp < 2) goto underflow;
double x = stack[--sp];
stack[sp-1] += x;
} break;
Repeat for each supported binary arithmetic operator. With the ability to token-paste, you can generate them all from a macro:
#define ARITH_BINOP(name, oper) case OP_##name: { \
if (sp < 2) goto underflow; \
double x = stack[--sp]; \
stack[sp-1] oper##= x; \
} break /* deliberate absence of semicolon */
and then, in the switch, you can just write
ARITH_BINOP(add, +);
ARITH_BINOP(sub, -);
ARITH_BINOP(mul, *);
/* etc */
I think, documentation says about cases like:
#define COMPST(x, y) x ## y
int
foo(int x)
{
return x COMPST(+, =) 2;
}
Of course macros can perform anything you can achieve in C code:
#define INCREMENT(x) ((x) += 1)
main() {
int n=42;
INCREMENT(n);
}
the line you read means another thing which I suspect you are not interested in...

Function-like macro definition in C

I'd like to define a function like MACRO . i.e.
#define foo(x)\
#if x>32\
x\
#else\
(2*x)\
#endif
that is,
if x>32, then foo(x) present x
else, foo(x) present (2*x)
but my GCC complains about:
int a = foo(31);
I think C preprocessor should be handle this correctly. since at compile time, it knows x=33. it could replace foo(33) with (2*33)
You can as follows
#define foo(x) ((x) > 32 ? (x) : (2 * (x)))
But that evaluates x multiple times. You can instead create a static function, which is cleaner
static int foo(int x) {
if(x > 32)
return x;
return 2 * x;
}
Then you are also able to pass things to foo that have side effects, and have the side effect happen only one time.
What you have written is using the #if, #else and #endif preprocessor directives, but you need to use language constructs if you pass variables to the macro and want to evaluate their values. Using if, and else statements as in the actual language constructs don't work either, because control flow statements don't evaluate to values. In other words, an if statement is steering control flow only ("if A, then execute B, else execute C"), not evaluating to any values.
#define \
foo(x) \
({ \
int xx = (x); \
int result = (xx > 32) ? xx : (2*xx); \
result; \
})
int a = foo(31);
Expands out to
int a = if 31>32
31
else
(2*31)
endif;
That's how C macros work, via simple, dumb substitution. If you expect gcc to do anything more complex or intelligent with them, then your expectation is erroneous.
Given that, it's easy to see why your code won't work. An alternative that would suffice for this example would be:
#define foo(x) (x > 32 ? x : 2*x)
On the other hand, I would question whether macros are really the appropriate tool for such a thing to begin with. Just put it in the function and the compiler will inline the code if it thinks it will speed it up.
Consider:
int x = rand()
int y = foo( x );
x is not known at compile time.
The problem is not about the theory: provided that you, for some reason, want to have a macro that expands differently according to the value of a parameter passed to it, and this parameter is a constant, known to the macro preprocessor, there's no reason why it couldn't work... for a generic macro processor... But cpp unluckly does not allow the presence of other macro processor "commands" into a macro definition...
So your
#define foo(x) \
#if x>32 \
x \
#else \
2*x \
#endif
does not expand to
#if X>32
X
#else
2*X
#endif
where X is the known parameter (so change X to e.g. 31), which requires another pass by the preprocessor.
Moreover newlines are ignored, while they are important for such an use; otherwise, the following could be considered as a trick (that need another preprocessing pass however)
#define foo(x,y) \
y if x>32 \
x \
y else \
2*x \
y endif
that with foo(20,#) produces
# if 20>32 20 # else 2*20 # endif
which would work, if it would be
# if 20>32
20
# else
2*20
# endif
... but it is not (and as said, the output of the preprocessor must be feeded to the preprocessor again...)
So my answer is that if you need these things, you can't use the C preprocessor; you should use a uncommon (not standard?) C preprocessor, or just another macro processor, and if you need the sort of things that "cpp" has to "integrate" itself with C, then you can't use a generic one (like M4) so easily...

Checking the return value of a function in a macro

I have core function which I can call from the customized module of the product.
function_core is the core function which will return and integer
we have a macro in header file:
#define func_cust function_core
I am calling
func_cust inside my customized code.
But inside the core we again call some other core function:
#define function_core main_core
so I cannot put in my customized code all the arguments.
I am calling this func_cust function call in many C files.
I need to check the return value of the function function_core like
if function_core returns x then I want to change the return value to 0 or else same return value will be returned.
For example I want to define a macro like this:
#define funct_cust ((function_core==x)?0:function_core)
Is this possible?
To be more specific this is what i need!!
#include<stdio.h>
#define sum_2 ((sum_1==11)?0:sum_1)
#define sum_1(a,b) sum(a,b)
int sum( int ,int);
int main()
{
int a,b,c;
a=5;
b=6;
c=sum_2(a,b);
printf("%d\n",c);
}
int sum(int x,int y)
{
return x+y;
}
this gives an error :
"test_fun.c", line 12.3: 1506-045 (S) Undeclared identifier sum_1.
I only have the access to play with this macro sum_2.
It's better to write an inline function (C99 supports this):
static const int x = ...;
static inline int funct_cust(void* args) {
int res = function_core(args);
if (res == x) return 0;
return res;
}
If you use gcc, you can use statement exprs:
#define funct_cust(args) ({ int res = function_core(args); res == x ? 0 : res; })
If you can add an actual function, it would be pretty easy:
int sanitize(int value, int x)
{
return (value == x) ? 0 : value;
}
Then just change your macro into
#define func_cust sanitize(func_core(), x)
This solves the otherwise hairy problem of not evaluating the function call twice, and not having to introduce a temporary (which is hard to do in a macro).
If evaluating twice is okay, then of course just do it like you outlined:
#define func_cust func_core() == x ? 0 : func_core()
Change it to (assuming a,b is constant)
#define sum_2(a,b) ({(sum_1(a,b)==11)?0:sum_1(a,b);})
#define sum_1 sum
int sum(int ,int);
This is not safe because a,b can be non constant expressions too. So you may want to create local variables holding the value of a,b so they are only evaluated once (improved)
#define sum_2(a,b) ({ \
typeof(a) _a = (a); \
typeof(b) _b = (b); \
sum_1(_a, _b) == 11 ? 0 : sum_1(_a,_b); \
})
#define sum_1 sum
int sum(int ,int);
Do not miss any of the curly braces, semi-colon in the last statement, and the slashes.

Resources