Issue
so , I was reading GCC documentation until I reached Statements and Declarations in Expressions section 6.1 , href="https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html#Statement-Exprs" rel="nofollow noreferrer">follow this link to reach the section I am talking about.
I came to these strange lines where GCC states that
This feature is especially useful in making macro definitions “safe” (so that they evaluate each operand exactly once). For example, the “maximum” function is commonly defined as a macro in standard C as follows:
#define max(a,b) ((a) > (b) ? (a) : (b))
But this definition computes either a or b twice, with bad results if the operand has side effects. In GNU C, if you know the type of the operands (here taken as int), you can avoid this problem by defining the macro as follows:
#define maxint(a,b) ({int _a = (a), _b = (b); _a > _b ? _a : _b; })
from my understand , GCC recommends knowing the type of the arguments, now I have many questions in my head.
why do I have to know the type of the arguments ? I mean C macros are just like text replacements , so I think
max(a,b)
will work just fine with any primitive data type whether it's integer, float, double, etc..I don't know how will
maxint(a,b)
work , I mean it's a strange signature of ternary operator , I mean for example in the next lines of code:#include <stdio.h> #define maxint(a,b) \ ({int _a = (a), _b = (b); _a > _b ? _a : _b; }) int main() { int x = 5; int y = 10; int z = maxint(x , y); printf("z = %d",z); }
z value will be 10 , which is a correct answer, and the next lines are the lines generated after preprocessing done by the compiler of the above code:
int main()
{
int x = 5;
int y = 10;
int z = ({int _a = (x), _b = (y); _a > _b ? _a : _b; });
printf("z = %d",z);
return 0;
}
my problem is in this line int z = ({int _a = (x), _b = (y); _a > _b ? _a : _b; });
, how does this line evaluate z to be 10 , I mean It's just a block of lines , there is no return value. I only see this line when evaluating at runtime to be
int z = ({int _a = (5), _b = (10); 10; });
as whole ternary operation will be replaced by the value 10,as (5 > 10 ? 5 : 10) will be replaced by 10, which doesn't make sense to me to assign a block of code to a primitive data type (which is z in my case)
- they said in the quoted lines above
But this definition computes either a or b twice
talking about this macro max(a,b)
, I don't understand how does this macro computes either a or b twice and how did macro maxint(a,b)
solve this problem ?
Solution
why do I have to know the type of the arguments ?
To evaluate the arguments once, in assignment.
( And you don't, you can use another gcc extension __auto_type
or __typeof__
. )
I mean it's a strange signature of ternary operator
It's a gcc extension called statement expression https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html .
It's just a block of lines , there is no return value
And from that documentation: The last thing in the compound statement should be an expression followed by a semicolon; the value of this subexpression serves as the value of the entire construct
. The value of _a > _b ? _a : _b;
is the last, and it serves as the "return value" of ({...})
.
how does this macro computes either a or b twice and how did macro maxint(a,b) solve this problem ?
Is explained in macro pitfalls in gcc documentation https://gcc.gnu.org/onlinedocs/cpp/Duplication-of-Side-Effects.html#Duplication-of-Side-Effects .
Many C programs define a macro min, for “minimum”, like this:
#define min(X, Y) ((X) < (Y) ? (X) : (Y))
When you use this macro with an argument containing a side effect, as shown here,
next = min (x + y, foo (z));
it expands as follows:
next = ((x + y) < (foo (z)) ? (x + y) : (foo (z)));
Answered By - KamilCuk Answer Checked By - Mildred Charles (WPSolving Admin)