This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 7 days ago.
Following snippet is from mac sdk signal.h:
#define sigemptyset(set) (*(set) = 0, 0)
just wonder what does , 0) do?
The macro expands to a comma expression: the left operand, evaluated first, sets the object pointed to by set to 0, then the right operand is evaluated and its value is the value of the whole expression, hence: 0.
In other words, the macro behaves like a function that always succeeds, success indicated by the return value 0.
Except for the type checking, the macro is equivalent to:
#include <signal.h>
int sigemptyset(sigset_t *set) {
*set = 0;
return 0;
}
Note that the <signal.h> header file also contains a prototype for this function:
int sigemptyset(sigset_t *);
In your code, a call sigemptyset(&sigset) invokes the macro, but you can force a reference to the library function by writing (sigemptyset)(&sigset) or by taking a pointer to the function. The macro allows for inline expansion without a change of prototype. clang can perform inline expansion at link time for small functions, but not for functions defined inside dynamic libraries.
The same trick is used for other functions in the header file, for which the , 0) is necessary for the expression to evaluate to 0 with type int:
#define sigaddset(set, signo) (*(set) |= __sigbits(signo), 0)
#define sigdelset(set, signo) (*(set) &= ~__sigbits(signo), 0)
#define sigemptyset(set) (*(set) = 0, 0)
#define sigfillset(set) (*(set) = ~(sigset_t)0, 0)
In this expression
(*(set) = 0, 0)
there is used the comma operator.
The result of the expression is 0.
As a side effect the object pointed to by the pointer set is set to 0.
From the C Standard (6.5.17 Comma operator)
2 The left operand of a comma operator is evaluated as a void
expression; there is a sequence point between its evaluation and that
of the right operand. Then the right operand is evaluated; the result
has its type and value.
Related
The below given code is written to satisfy the condition (x == x+2) to be returning true in C.
#include<stdio.h>
#define x 2|0
int main()
{
printf("%d",x==x+2);
return 0;
}
In the above code why the printf() is printing 2 ( if I write x+3 I get 3 and so on ).
Can someone explain how the given macro is working.
What is the use of | operator in C and what does the macro
#define x 2|0
mean? I read about macros in other questions but no question explained similar kind of example.
TL;DR; Read about operator precedence.
+ binds higher than == which binds higher than |.
After preprocessing, your printf() statement looks like
printf("%d",2|0==2|0+2);
which is the same as
printf("%d",2|(0==2)|(0+2));
which is
printf("%d",2|0|2);
Word of advice: Do not write this type of code in real scenario. With minimal level of compiler warning enabled, your code produces
source_file.c: In function ‘main’:
source_file.c:4:12: warning: suggest parentheses around comparison in operand of ‘|’ [-Wparentheses]
#define x 2|0
^
source_file.c:8:21: note: in expansion of macro ‘x’
printf("%d\n\n",x==x+2);
^
source_file.c:4:12: warning: suggest parentheses around arithmetic in operand of ‘|’ [-Wparentheses]
#define x 2|0
^
source_file.c:8:24: note: in expansion of macro ‘x’
printf("%d\n\n",x==x+2);
So, the moment you change the MACRO definition to something sane, like
#define x (2|0)
the result will also change, as the explicit precedence then will be guaranteed by the parenthesis.
After running the preprocessor, gcc -E main.c you will get:
int main()
{
printf("%d",2|0==2|0 +2);
return 0;
}
Since (0==2) is 0, 2|0|2
I saw a program in C that had code like the following:
static void *arr[1] = {&& varOne,&& varTwo,&& varThree};
varOne: printf("One") ;
varTwo: printf("Two") ;
varThree: printf("Three") ;
I am confused about what the && does because there is nothing to the left of it. Does it evaluate as null by default? Or is this a special case?
Edit:
Added some more information to make the question/code more clear for my question.
Thank you all for the help. This was a case of the gcc specific extension.
It's a gcc-specific extension, a unary && operator that can be applied to a label name, yielding its address as a void* value.
As part of the extension, goto *ptr; is allowed where ptr is an expression of type void*.
It's documented here in the gcc manual.
You can get the address of a label defined in the current function (or
a containing function) with the unary operator &&. The value has
type void *. This value is a constant and can be used wherever a
constant of that type is valid. For example:
void *ptr;
/* ... */
ptr = &&foo;
To use these values, you need to be able to jump to one. This is done
with the computed goto statement, goto *exp;. For example,
goto *ptr;
Any expression of type void * is allowed.
As zwol points out in a comment, gcc uses && rather than the more obvious & because a label and an object with the same name can be visible simultaneously, making &foo potentially ambiguous if & means "address of label". Label names occupy their own namespace (not in the C++ sense), and can appear only in specific contexts: defined by a labeled-statement, as the target of a goto statement, or, for gcc, as the operand of unary &&.
This is a gcc extension, known as "Labels as Values". Link to gcc documentation.
In this extension, && is a unary operator that can be applied to a label. The result is a value of type void *. This value may later be dereferenced in a goto statement to cause execution to jump to that label. Also, pointer arithmetic is permitted on this value.
The label must be in the same function; or in an enclosing function in case the code is also using the gcc extension of "nested functions".
Here is a sample program where the feature is used to implement a state machine:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
void *tab[] = { &&foo, &&bar, &&qux };
// Alternative method
//ptrdiff_t otab[] = { &&foo - &&foo, &&bar - &&foo, &&qux - &&foo };
int i, state = 0;
srand(time(NULL));
for (i = 0; i < 10; ++i)
{
goto *tab[state];
//goto *(&&foo + otab[state]);
foo:
printf("Foo\n");
state = 2;
continue;
bar:
printf("Bar\n");
state = 0;
continue;
qux:
printf("Qux\n");
state = rand() % 3;
continue;
}
}
Compiling and execution:
$ gcc -o x x.c && ./x
Foo
Qux
Foo
Qux
Bar
Foo
Qux
Qux
Bar
Foo
I'm not aware of any operator that works this way in C.
Depending on the context, the ampersand in C can mean many different things.
Address-Of operator
Right before an lvalue, e.g.
int j;
int* ptr = &j;
In the code above, ptr stores the address of j, & in this context is taking the address of any lvalue. The code below, would have made more sense to me if it was written that way.
static int varOne;
static int varTwo;
static int varThree;
static void *arr[1][8432] = { { &varOne,&varTwo, &varThree } };
Logical AND
The logical AND operator is more simple, unlike the operator above, it's a binary operator, meaning it requires a left and right operand. The way it works is by evaluating the left and right operand and returning true, iff both are true, or greater than 0 if they are not bool.
bool flag = true;
bool flag2 = false;
if (flag && flag2) {
// Not evaluated
}
flag2 = true;
if (flag && flag2) {
// Evaluated
}
Bitwise AND
Another use of the ampersand in C, is performing a bitwise AND. It's similar as the logical AND operator, except it uses only one ampersand, and performs an AND operation at the bit level.
Let's assume we have a number and that it maps to the binary representation shown below, the AND operation works like so:
0 0 0 0 0 0 1 0
1 0 0 1 0 1 1 0
---------------
0 0 0 0 0 0 1 0
In C++ land, things get more complicated. The ampersand can be placed after a type as to denote a reference type (you can think of it as a less powerful but safe kind of pointer), then things get even more complicated with 1) r-value reference when two ampersands are placed after a type. 2) Universal references when two ampersands are placed after a template type or auto deducted type.
I think your code probably compiles only in your compiler due to an extension of some sorts. I was thinking of this https://en.wikipedia.org/wiki/Digraphs_and_trigraphs#C but I doubt that's the case.
I am not exactly sure what to title this. But, this is the third time I have seen this phenomena in a C macro.
#define sigemptyset(what) (*(what) = 0, 0)
^
eh? why not just ((*what) = 0)
Is there a point to that extra zero? To my understanding (1, 0, 0, 0), for example, would just evaluate to 1 (the first entry).
The comma operator yields the value of its right operand, not the left operand.
UPDATE: as pointed out by #Kninnug in the comments, sigemptyset is a POSIX function specified to return an int (specifications: here). By using (*(what) = 0, 0) it guarantees that the macro yields an int even if *(what) is of another type than int (the sigemptyset argument should be of type sigset_t).
Two things come to my mind with your macro definition:
If it had (void *) 0 as the right , operand, it could mimic a function that returns a null pointer:
#define sigemptyset(what) (*(what) = 0, (void *) 0)
int *p = sigemptyset(q);
It can be useful if all your other sig functions are supposed to return pointers.
The second thing that comes to my mind is to allow debugging by changing the 0 with a printf call when needed:
#define sigemptyset(what) (*(what) = 0, printf("sigemptyset\n"))
This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 7 years ago.
I am trying to get some understanding about how pass by value & return are happening in C functions. I cam across a piece of code as follows:
#include <stdio.h>
int fun(int ii, int jj)
{
int kk, ll;
kk = ii + jj;
ll = ii * jj;
return (kk,ll);
}
int main()
{
int i=4, j=5, k, l;
k = fun(i, j);
l = fun(i, j);
printf("%d %d\n", k, l);
return 0;
}
Now apparently I am not getting any errors when I am trying to return 2 values through fun().
Also, the value that is returned by fun() is ll i.e 20 (=4*5) and not kk. Further, If I rewrite the return statement as :
return (ll,kk);
the value returned is that of kk ie. 9 (=4+5).
Query: Why this is so?
In your code, in the return statement
return (kk,ll);
you're using the comma operator. By the property of the comma operator, you're not returning two values, rather you're returning the second operand of the comma operator only.
To elaborate, let's check the property of the comma operator, directly quoting the standard, C11, chapter §6.5.17, (emphasis mine)
The left operand of a comma operator is evaluated as a void expression; there is a sequence point between its evaluation and that of the right operand. Then the right operand is evaluated; the result has its type and value.
So, essentially, a return statement like
return (kk,ll);
is same as
return ll;
Hope you can figure out the other case.
That said, the recommended signature for main() is int main(int argc, char*argv[]) or , at least, int main(void).
What do you expect when returning an int? C does not support tuples.
You are using the comma-operator. (ll, kk) is a single expression with the inner expressions (seperated by , - thus the name) being evaluated left to right. All but the rightmost (you can have more than two sub-expressions) results are discarded and the rightmost result is the result of the whole expression. Actually the parenthesis are unnecessary and do not change anything.
You are using the comma operator.
The comma operator (represented by the token ,) is a binary operator that evaluates its first operand and discards the result, and then evaluates the second operand and returns this value (and type).
This question already has answers here:
C macros and use of arguments in parentheses
(2 answers)
Closed 5 years ago.
I tried to play with the definition of the macro SQR in the following code:
#define SQR(x) (x*x)
int main()
{
int a, b=3;
a = SQR(b+5); // Ideally should be replaced with (3+5*5+3), though not sure.
printf("%d\n",a);
return 0;
}
It prints 23. If I change the macro definition to SQR(x) ((x)*(x)) then the output is as expected, 64. I know that a call to a macro in C replaces the call with the definition of the macro, but I still can’t understand, how it calculated 23.
Pre-processor macros perform text-replacement before the code is compiled so
SQR(b+5) translates to
(b+5*b+5) = (6b+5) = 6*3+5 = 23
Regular function calls would calculate the value of the parameter (b+3) before passing it to the function, but since a macro is pre-compiled replacement, the algebraic order of operations becomes very important.
Consider the macro replacement using this macro:
#define SQR(x) (x*x)
Using b+5 as the argument. Do the replacement yourself. In your code, SQR(b+5) will become: (b+5*b+5), or (3+5*3+5). Now remember your operator precedence rules: * before +. So this is evaluated as: (3+15+5), or 23.
The second version of the macro:
#define SQR(x) ((x) * (x))
Is correct, because you're using the parens to sheild your macro arguments from the effects of operator precedence.
This page explaining operator preference for C has a nice chart. Here's the relevant section of the C11 reference document.
The thing to remember here is that you should get in the habit of always shielding any arguments in your macros, using parens.
Because (3+5*3+5 == 23).
Whereas ((3+5)*(3+5)) == 64.
The best way to do this is not to use a macro:
inline int SQR(int x) { return x*x; }
Or simply write x*x.
The macro expands to
a = b+5*b+5;
i.e.
a = b + (5*b) + 5;
So 23.
After preprocessing, SQR(b+5) will be expanded to (b+5*b+5). This is obviously not correct.
There are two common errors in the definition of SQR:
do not enclose arguments of macro in parentheses in the macro body, so if those arguments are expressions, operators with different precedences in those expressions may cause problem. Here is a version that fixed this problem
#define SQR(x) ((x)*(x))
evaluate arguments of macro more than once, so if those arguments are expressions that have side effect, those side effect could be taken more than once. For example, consider the result of SQR(++x).
By using GCC typeof extension, this problem can be fixed like this
#define SQR(x) ({ typeof (x) _x = (x); _x * _x; })
Both of these problems could be fixed by replacing that macro with an inline function
inline int SQR(x) { return x * x; }
This requires GCC inline extension or C99, See 6.40 An Inline Function is As Fast As a Macro.
A macro is just a straight text substitution. After preprocessing, your code looks like:
int main()
{
int a, b=3;
a = b+5*b+5;
printf("%d\n",a);
return 0;
}
Multiplication has a higher operator precedence than addition, so it's done before the two additions when calculating the value for a. Adding parentheses to your macro definition fixes the problem by making it:
int main()
{
int a, b=3;
a = (b+5)*(b+5);
printf("%d\n",a);
return 0;
}
The parenthesized operations are evaluated before the multiplication, so the additions happen first now, and you get the a = 64 result that you expect.
Because Macros are just string replacement and it is happens before the completion process. The compiler will not have the chance to see the Macro variable and its value. For example: If a macro is defined as
#define BAD_SQUARE(x) x * x
and called like this
BAD_SQUARE(2+1)
the compiler will see this
2 + 1 * 2 + 1
which will result in, maybe, unexpected result of
5
To correct this behavior, you should always surround the macro-variables with parenthesis, such as
#define GOOD_SQUARE(x) (x) * (x)
when this macro is called, for example ,like this
GOOD_SQUARE(2+1)
the compiler will see this
(2 + 1) * (2 + 1)
which will result in
9
Additionally, Here is a full example to further illustrate the point
#include <stdio.h>
#define BAD_SQUARE(x) x * x
// In macros alsways srround the variables with parenthesis
#define GOOD_SQUARE(x) (x) * (x)
int main(int argc, char const *argv[])
{
printf("BAD_SQUARE(2) = : %d \n", BAD_SQUARE(2) );
printf("GOOD_SQUARE(2) = : %d \n", GOOD_SQUARE(2) );
printf("BAD_SQUARE(2+1) = : %d ; because the macro will be \
subsituted as 2 + 1 * 2 + 1 \n", BAD_SQUARE(2+1) );
printf("GOOD_SQUARE(2+1) = : %d ; because the macro will be \
subsituted as (2 + 1) * (2 + 1) \n", GOOD_SQUARE(2+1) );
return 0;
}
Just enclose each and every argument in the macro expansion into parentheses.
#define SQR(x) ((x)*(x))
This will work for whatever argument or value you pass.