LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 09-02-2011, 11:25 PM   #1
bhatia.ankur8
LQ Newbie
 
Registered: Jul 2010
Location: india
Posts: 13

Rep: Reputation: 0
Unhappy c programming


hello alll...
can someone please explain me the output of the following..
Code:
‎#include <stdio.h>

int main(int argc, char* argv[])
{
int a = 1, b = 2, c = 3;
if( !((a = 0) && (c += 1)) || (b += 2))
printf("a= %d, b= %d, c= %d", a, b, c);
return 0;
}
 
Click here to see the post LQ members have rated as the most helpful post in this thread.
Old 09-03-2011, 12:04 AM   #2
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
It's called "short circuit evaluation". C *stops* evaluating an expression with "&&" or "||" as soon as it has a definite true/false answer:

Code:
#include <stdio.h>

int main(int argc, char* argv[])
{
  int a = 1, b = 2, c = 3;  // Declare some variables
  if( !((a = 0) && (c += 1)) || (b += 2))  // if ( !(0 && 4)  || (4)) => "TRUE" AT "a=0"
    printf("a= %d, b= %d, c= %d", a, b, c); // Print data: 0, 2, 3
  return 0;
}
Here's more info:
http://en.wikipedia.org/wiki/Short-circuit_evaluation

'Hope that helps
 
3 members found this post helpful.
Old 09-03-2011, 12:43 PM   #3
mf93
Member
 
Registered: Jun 2009
Distribution: Debian Squeeze, centOS
Posts: 229

Rep: Reputation: 36
in your if statement you are not comparing(i.e a==1), you are actually testing the success of the assignment functions mapped to the operators =, and += respectively. As a result, unless something is wrong with your ram, they will always *return* true, but will actually assign those values to a,b,and c, causing the output to be always be displayed as "a=0 b=4 c=4".
 
0 members found this post helpful.
Old 09-03-2011, 12:45 PM   #4
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by mf93 View Post
in your if statement you are not comparing(i.e a==1), you are actually testing the success of the assignment functions mapped to the operators =, and += respectively. As a result, unless something is wrong with your ram, they will always *return* true, but will actually assign those values to a,b,and c, causing the output to be always be displayed as "a=0 b=4 c=4".
That isn't true. The return value of an assignment is the new value of the variable.
Kevin Barry
 
1 members found this post helpful.
Old 09-03-2011, 11:30 PM   #5
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
Okay, just to be completely pedantic, it isn't a 'return' value (which is reserved for functions), but simply the evaluation of an expression. The value of an assignment expression is the value assigned to the lvalue on the left hand side of the assignment operator.
What mf93 said is just not even close to any part of the C language.
The OP's sample code looks like homework, and paulsm4 has correctly seized on the essence of the question.

--- rod.

Last edited by theNbomr; 09-03-2011 at 11:32 PM.
 
Old 09-04-2011, 01:11 AM   #6
ArthurSittler
Member
 
Registered: Jul 2008
Distribution: Slackware
Posts: 124

Rep: Reputation: 31
MF93 pointed out that this is one of the most notorious pitfalls of C. C does not distinguish a boolean type. In C, any nonzero integer is true. Using assignment operator "=" instead of comparison operator "==" as a logic parameter in a conditional expression will always be true unless the assigned value is zero. This can cause hidden bugs which pass program testing and are detected after the program is delivered to the end user. The compiler can generate warnings for this syntax. Setting all warnings as errors in the compiler and editing the source code to clear all warnings can prevent this bug.
 
Old 09-04-2011, 01:21 AM   #7
paulsm4
LQ Guru
 
Registered: Mar 2004
Distribution: SusE 8.2
Posts: 5,863
Blog Entries: 1

Rep: Reputation: Disabled
This "pitfall" is also a very powerful technique. There are perfectly legitimate reasons to WANT to a) do an assignment, b) treat the result as a boolean, and perhaps even c) string several of these expressions together.

The lesson to be learned isn't to AVOID it. But rather, to UNDERSTAND it. And, of course, to exploit this feature whenever/wherever applicable

PS:
What mf93 said is flat-out wrong.
 
1 members found this post helpful.
Old 09-04-2011, 09:05 AM   #8
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
Quote:
Originally Posted by paulsm4 View Post
This "pitfall" is also a very powerful technique. There are perfectly legitimate reasons to WANT to a) do an assignment, b) treat the result as a boolean, and perhaps even c) string several of these expressions together.

The lesson to be learned isn't to AVOID it. But rather, to UNDERSTAND it. And, of course, to exploit this feature whenever/wherever applicable
Couldn't agree more. I like to use this feature, and do so often. It bothers me that modern compilers seem to assume that I've done so erroneously, and by default flag it as a warning that I have to specifically over-ride.
--- rod
 
1 members found this post helpful.
Old 09-04-2011, 09:52 AM   #9
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by theNbomr View Post
Okay, just to be completely pedantic, it isn't a 'return' value (which is reserved for functions), but simply the evaluation of an expression. The value of an assignment expression is the value assigned to the lvalue on the left hand side of the assignment operator.
Sorry, I was thinking in C++ where operators are functions and assignments return lvalues.
Quote:
Originally Posted by ArthurSittler View Post
MF93 pointed out that this is one of the most notorious pitfalls of C. C does not distinguish a boolean type. In C, any nonzero integer is true. Using assignment operator "=" instead of comparison operator "==" as a logic parameter in a conditional expression will always be true unless the assigned value is zero. This can cause hidden bugs which pass program testing and are detected after the program is delivered to the end user. The compiler can generate warnings for this syntax. Setting all warnings as errors in the compiler and editing the source code to clear all warnings can prevent this bug.
I think you mean "will always be the assigned value" since not just any non-zero value results. Ultimately if ((a = 4)) becomes if (4), which meets the condition of "trueness".
Code:
a = b = c = 4;     /*<-- this sets all three to '4'*/
a = (b = (c = 4)); /*<-- also sets all three to '4' (same thing made explicit)*/
Kevin Barry
 
Old 09-04-2011, 10:14 AM   #10
sundialsvcs
LQ Guru
 
Registered: Feb 2004
Location: SE Tennessee, USA
Distribution: Gentoo, LFS
Posts: 10,636
Blog Entries: 4

Rep: Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933Reputation: 3933
I'll chime-in with a politely dissenting opinion, if I may.

I've spent most of my ~30 year career as a consultant in the literal sense of the word. It's not quite that "I pick up the pieces where other programmers and projects have screwed-up things royally," but, well, it is pretty-damm close to that. And so I have seen a lot of "clever" code like that, and I have rewritten a lot of it.

A favorite saying is, "at 3 billion ops a second, no one can hear you scream." CPUs today are unbelievably fast ... but there is also a subtle and therefore often-overlooked reason why they are so fast: the compiler. Processors like the x86 have highly "pipelined" architectures and lots of very-strange instructions. Intel and AMD work hand-in-hand with compiler writers (and publish their own compilers) specifically so that code will be generated, and generated "in the right way," to fully exploit the architecture ... which is designed to be fully-exploited by code that has been generated "in the right way."

So, here's my simple advice: don't be clever ... don't even try anymore. Especially if the compiler is issuing a warning or informational message, pay attention to that message and do whatever you have to do to make that message go away. Your code should compile clean: no errors, no warnings, no hints.

And of course there is another, even more compelling reason: code that is "clever," that therefore cannot be "instantly and accurately read and understood by a distracted human being at first glance," is absurdly expensive. Sure, it might over the course of your entire lifetime save as much as one tenth of one second of actual wall-time, but the cost of a bug or the cost of difficulty in maintenance is beyond calculation. Thousands of dollars. Millions. No kidding.

Make your code "stupid-easy to read." Your compiler will thank you (and will work magic on your behalf). Your colleagues, employers, and customers will thank you even more.
 
1 members found this post helpful.
Old 09-06-2011, 03:03 AM   #11
bhatia.ankur8
LQ Newbie
 
Registered: Jul 2010
Location: india
Posts: 13

Original Poster
Rep: Reputation: 0
thankyou so much to all of you.. it was indeed very helpful.
 
Old 09-06-2011, 03:39 AM   #12
MrCode
Member
 
Registered: Aug 2009
Location: Oregon, USA
Distribution: Arch
Posts: 864
Blog Entries: 31

Rep: Reputation: 148Reputation: 148
WARNING: THIS POST HAS BEEN WRITTEN BY SOMEWHAT OF A C N00B

I've found that evaluating the "success" or "failure" of an assignment operation (i.e. zero or non-zero assignment) can be useful in checking the return value of a function that returns NULL on error:

Code:
SDL_Surface* disp = NULL;

if(!(disp = SDL_SetVideoMode(1,1,BPP,SDL_SWSURFACE | SDL_DOUBLEBUF)))
{
    fprintf(stderr,"SDL Error: %s\n",SDL_GetError());
    return 1;
}
If this is horrible advice, then I apologize in advance.

Last edited by MrCode; 09-06-2011 at 03:41 AM.
 
Old 09-07-2011, 08:16 AM   #13
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
I find MrCode's code perfectly readable, and fully acceptable C idiom. Modern compilers and sundialsvcs seem to differ.

I would differ on the use of terms such as success/failure to describe the assignment. The assignment always succeeds, or the computer is broken. The assignment constitutes an expression, which, depending on the context, evaluates to a boolean. The 'success/failure' aspect may be a condition of the function call, again depending on context.
--- rod.
 
Old 09-07-2011, 02:06 PM   #14
MTK358
LQ 5k Club
 
Registered: Sep 2009
Posts: 6,443
Blog Entries: 3

Rep: Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723Reputation: 723
Quote:
Originally Posted by theNbomr View Post
Modern compilers and sundialsvcs seem to differ.
I don't think of it as a way to cleverly try to optimize code, but as a simple, readable way of doing things that would be much more complicated if "=" was not an expression.
 
Old 09-07-2011, 02:55 PM   #15
MrCode
Member
 
Registered: Aug 2009
Location: Oregon, USA
Distribution: Arch
Posts: 864
Blog Entries: 31

Rep: Reputation: 148Reputation: 148
@MTK

I think the argument sundialsvcs is trying to make is that expressions like the one in my example code above aren't "stupid simple to read" and should thus be avoided, and preferably replaced with something like this:

Code:
SDL_Surface* disp = NULL;

disp = SDL_SetVideoMode(1,1,BPP,SDL_SWSURFACE | SDL_DOUBLEBUF);

if(disp == NULL)
{
    fprintf(stderr,"SDL Error: %s\n",SDL_GetError());
    return 1;
}
While it's more "readable" (for a given definition of "readable"), it isn't as concise/compact IMO. Of course, something like this (from K&R, according to Wikipedia):

Code:
void strcpy(char* s,char* t) { while(*s++ = *t++); }
…would be considered blasphemy.

Last edited by MrCode; 09-07-2011 at 02:57 PM.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:35 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration