# Thread: use of and or

1. ## use of and or

I know I can do this:

if ((a == x) || (a == z) || (b == x) || (b == z))

but is there a way to shorten it like this:

if (a||b == x||z)

which doesn't work...i hope i'm not answering my own question...

2. No, you have to do it the long way.

3. In this example, will C skip evaluation of the other conditions should a==x?

4. In this example, will C skip evaluation of the other conditions should a==x?
Yes, if (a == x) is true then the other comparisons will not be evaluated.

5. Originally Posted by noops
In this example, will C skip evaluation of the other conditions should a==x?
Yes.

6. yes.

7. A three-way tie! You all get a cookie!

Does the compiler 'unroll' compound evaluation statements in a manner like so:

Code:
if ((a == x) || (a == z) || (b == x) || (b == z))
{
/* do stuff */
}
to:

Code:
if (a == x)
{
goto dostuff;
}
else if (a == z)
{
goto dostuff;
}
else if (b == x)
{
goto dostuff;
}
else if (b == z)
{
goto dostuff;
}

goto dontdostuff:

dostuff:
/* do stuff */

dontdostuff:
/* continue with rest of program */
I've never used goto so this could be wrong but you get the gist. And is this implementation defined so something like:
Code:
if ((a == x) || (i++ < 10))
Would result in undefined behavior? Will i++ not happen if a==x?

8. Originally Posted by noops
A three-way tie! You all get a cookie!

Does the compiler 'unroll' compound evaluation statements in a manner like so:

Code:
if ((a == x) || (a == z) || (b == x) || (b == z))
{
/* do stuff */
}
to:

Code:
if (a == x)
{
goto dostuff;
}
else if (a == z)
{
goto dostuff;
}
else if (b == x)
{
goto dostuff;
}
else if (b == z)
{
goto dostuff;
}

goto dontdostuff:

dostuff:
/* do stuff */

dontdostuff:
/* continue with rest of program */
I've never used goto so this could be wrong but you get the gist. And is this implementation defined so something like:
Code:
if ((a == x) || (i++ < 10))
Would result in undefined behavior? Will i++ not happen if a==x?
I have no idea whether it gets unrolled, but it wouldn't surprise me.

The second is not undefined behavior, but i++ won't happen with a==x. (This is often used in things like
Code:
if (intptr == NULL || *intptr == 10)
so that the dereference won't happen if intptr is NULL.

9. more like
Code:
if (a == x)
{
if (a == z)
{
if (b == x)
{
if (b == z)
{
/* do stuff */
}
}
}
}

10. Originally Posted by robwhit
more like
Code:
if (a == x)
{
if (a == z)
{
if (b == x)
{
if (b == z)
{
/* do stuff */
}
}
}
}
Wouldn't that be for &&?
The second is not undefined behavior, but i++ won't happen with a==x. (This is often used in things like
Code:
if (intptr == NULL || *intptr == 10)
so that the dereference won't happen if intptr is NULL.
Thanks, I was actually trying to think of a sane case where you would rely on this behavior.

11. Oh yeah... haha...

Then yeah it would be similar to what you have there. Might not be the same thing, but similar. You could output assembly and see what it does.

12. To generate assembly with GCC, use the -S flag (note the uppercase 'S' -- lowercase 's' means strip symbols).
Code:
gcc -S source.c
cat source.s
Note that you might want to disable optimisations, or enable them, depending on what you're interested in.

13. Originally Posted by noops
A three-way tie! You all get a cookie!

Does the compiler 'unroll' compound evaluation statements in a manner like so:

Code:
if ((a == x) || (a == z) || (b == x) || (b == z))
{
/* do stuff */
}
to:

Code:
if (a == x)
{
goto dostuff;
}
else if (a == z)
{
goto dostuff;
}
else if (b == x)
{
goto dostuff;
}
else if (b == z)
{
goto dostuff;
}

goto dontdostuff:

dostuff:
/* do stuff */

dontdostuff:
/* continue with rest of program */
I've never used goto so this could be wrong but you get the gist.
From what I have seen, some code might look like:

Test condition 1.
Test condition 2.
...
Execute stuff if all conditions were true.
Label end.

14. Originally Posted by dwks
To generate assembly with GCC, use the -S flag (note the uppercase 'S' -- lowercase 's' means strip symbols).
Code:
gcc -S source.c
cat source.s
Note that you might want to disable optimisations, or enable them, depending on what you're interested in.
Here's the result (I just cut out the portion that looked meaningful):
Code:
/* C */
int a = 0,
b = 1,
x = 1,
z = 0;
if ((a == x) || (a == z) || (b == x) || (b == z))
a = 5;

/* ASM */

movl	\$0, -4(%ebp)
movl	\$1, -8(%ebp)
movl	\$1, -12(%ebp)
movl	\$0, -16(%ebp)
movl	-4(%ebp), %eax
cmpl	-12(%ebp), %eax
je	L3
movl	-4(%ebp), %eax
cmpl	-16(%ebp), %eax
je	L3
movl	-8(%ebp), %eax
cmpl	-12(%ebp), %eax
je	L3
movl	-8(%ebp), %eax
cmpl	-16(%ebp), %eax
je	L3
jmp	L2
L3:
movl	\$5, -4(%ebp)
L2:
movl	\$0, %eax
leave
ret
Now I have about 10 minutes experience with assembly but it looks to be doing the same thing I unrolled in C. Except I used else needlessly.

15. Yeah, it is.
je stands for "jump if equal", and jmp is just jump.
Although GCC chose to do it the "other way" around than what I expected the compiled code to look like. But it doesn't matter, really. It works.
( Again, GCC's asm syntax sucks =( )