use of and or

This is a discussion on use of and or within the C Programming forums, part of the General Programming Boards category; I know I can do this: if ((a == x) || (a == z) || (b == x) || (b ...

  1. #1
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    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...
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  2. #2
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    No, you have to do it the long way.

  3. #3
    * noops's Avatar
    Join Date
    Jun 2008
    Posts
    108
    In this example, will C skip evaluation of the other conditions should a==x?

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    21,397
    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.
    C + C++ Compiler: MinGW port of GCC
    Version Control System: Bazaar

    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Quote Originally Posted by noops View Post
    In this example, will C skip evaluation of the other conditions should a==x?
    Yes.

  6. #6
    & the hat of GPL slaying Thantos's Avatar
    Join Date
    Sep 2001
    Posts
    5,681
    yes.

  7. #7
    * noops's Avatar
    Join Date
    Jun 2008
    Posts
    108
    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. #8
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Quote Originally Posted by noops View Post
    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. #9
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    more like
    Code:
    if (a == x)
    {
        if (a == z)
        {
            if (b == x)
            {
                if (b == z)
                {
                    /* do stuff */
                }
            }
        }
    }
    Last edited by robwhit; 08-28-2008 at 12:47 PM.

  10. #10
    * noops's Avatar
    Join Date
    Jun 2008
    Posts
    108
    Quote Originally Posted by robwhit View Post
    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. #11
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    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. #12
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,046
    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.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  13. #13
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,420
    Quote Originally Posted by noops View Post
    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.
    If not true, jump to end.
    Test condition 2.
    If not true, jump to end.
    ...
    Execute stuff if all conditions were true.
    Label end.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    * noops's Avatar
    Join Date
    Jun 2008
    Posts
    108
    Quote Originally Posted by dwks View Post
    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. #15
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,420
    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 =( )
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21