LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   c programming (https://www.linuxquestions.org/questions/programming-9/c-programming-900809/)

bhatia.ankur8 09-02-2011 11:25 PM

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;
}


paulsm4 09-03-2011 12:04 AM

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

mf93 09-03-2011 12:43 PM

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".

ta0kira 09-03-2011 12:45 PM

Quote:

Originally Posted by mf93 (Post 4460553)
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

theNbomr 09-03-2011 11:30 PM

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.

ArthurSittler 09-04-2011 01:11 AM

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.

paulsm4 09-04-2011 01:21 AM

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.

theNbomr 09-04-2011 09:05 AM

Quote:

Originally Posted by paulsm4 (Post 4460886)
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

ta0kira 09-04-2011 09:52 AM

Quote:

Originally Posted by theNbomr (Post 4460842)
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 (Post 4460883)
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

sundialsvcs 09-04-2011 10:14 AM

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." :tisk: Your compiler will thank you (and will work magic on your behalf). Your colleagues, employers, and customers will thank you even more.

bhatia.ankur8 09-06-2011 03:03 AM

thankyou so much to all of you.. it was indeed very helpful.

MrCode 09-06-2011 03:39 AM

WARNING: THIS POST HAS BEEN WRITTEN BY SOMEWHAT OF A C N00B :p

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. :(

theNbomr 09-07-2011 08:16 AM

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.

MTK358 09-07-2011 02:06 PM

Quote:

Originally Posted by theNbomr (Post 4463860)
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.

MrCode 09-07-2011 02:55 PM

@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. :D


All times are GMT -5. The time now is 10:55 PM.