I would like to understand the logic behind the output - c

#include<stdio.h>
int main()
{
int value = 0 ;
if(value)
printf("0");
printf("1");
printf("2");
return 0;
}
The output of the above code is 12
but when I tweak the code by adding curly brackets the output differs
#include<stdio.h>
int main()
{
int value = 0 ;
if(value)
{
printf("0\n");
printf("1\n");
printf("2\n");
}
return 0;
}
After adding curly brackets I didn't get an output.
When I change the declared variable to 1 I expected the program to only output the line printf("2") because when the value = 0 it gave 12 as the output excluding the first printf statment, So I expected changing the assigned variable value = 1 as the output would exclude both the first and second printf statments, but it didn't. This made me more confused.
Summary:
If there is no curly bracket{} in the code it gives a different output for the same code with curly brackets
When I declare value=1 or any other number program prints 012(in both codes).
I would like to know why is this happening.
Thank you.

When you see
if ( condition )
stuff
it means "if condition is true, do stuff". But you have to be clear on what the condition is, and what the stuff is.
In C, the condition can be any expression, any expression at all. It can be a number like 0, or a variable like value, or a more complicated expression like i > 1 && i < 10. And, super important: the interpretation of the value is that 0 means "false", and anything else — any other value at all — means "true".
And then, what about the stuff? You can either have one statement, or several statements enclosed in curly braces { }.
If you have one statement, the if( condition ) part controls whether you do that one statement or not. If you have several statements enclosed in { }, the if( condition ) part controls whether you do that whole block or not.
So when you said
if(value)
printf("0");
printf("1");
printf("2");
you had one statement — just one — controlled by the if. If value was 0, it would not print 0.
If value was anything other than 0, it would print 0.
And then, it would always print 2 and 3, no matter what.
That's confusing to look at, which is why people always say that proper indentation is important — if you had written it as
if(value)
printf("0");
printf("1");
printf("2");
then the indentation would have accurately suggested the actual control flow.
And then when you said
if(value)
{
printf("0\n");
printf("1\n");
printf("2\n");
}
now all three statements are in a block, so they're all controlled by the if.
If value was 0, it won't print anything.
If value was anything other than 0, it will print all three.

In c an int can be evaluated true if the value is not 0 otherwise it is ecaluated as false. Additionally as mentioned in the comments, if statements without brakets only apply to the next statement, which is why your output differs there.

The code
if(value)
printf("0");
printf("1");
printf("2");
is interpreted as
if(value)
{
printf("0");
}
printf("1");
printf("2");
printf("0"); will be executed if value is non-zero; printf("1"); and printf("2"); will be executed unconditionally.
In the code
if(value)
{
printf("0\n");
printf("1\n");
printf("2\n");
}
all three printf statements will be executed only if value is non-zero.

Related

Why is the output different in the short version of if condition when compared to its expanded version?

int a = 0;
a = 7 > 2 ? printf("6") : printf("4");
printf ("%d",a);
The ouput of this block is :
61
I tried the code in its expanded form
int a = 0 ;
if(7>2)
{
printf("6");
}
else
{
printf("4");
}
printf("%d",a);
Here I the output was:
60
I would like to get an explanation on why the output differs.
The first statement assigns the return value of printf to a. printf returns the number of bytes that were written. In this case that is 1. In the second expanded version, a is not assigned. Here is an actually equivalent version to the original:
int a = 0;
if(7>2)
{
a = printf("6");
}
else
{
a = printf("4");
}
printf("%d",a);
They are completely different.
To make them identical:
int a = 0 ;
if(7>2)
{
a = printf("6");
}
else
{
a = printf("4");
}
printf("%d",a);
cond?val1:val2 is the ternary operator. It is not supposed to be a control structure (like if, for or while). It is an operator. To build expression (things that have a value) rather than instruction (things that does things).
Frontier is fuzzier in C than in other languages, because instructions have a value (including void) and expression have potential side-effects.
But, well, you use cond?val1:val2 when you want to get the result. As you did, since you assigned the result to a.
And the result here is the result of printf("6"), that is 1, since printf returns the number of printed characters. Note that there is no real doubt, since even if 7 were smaller than 2, result would still have been 1. Since you print that result, it is normal to have a 1 printed after the 6.
(Just to be clear, even if I assume you know that already, what you did is print string "6" and then number 1, which is the result of 1st printf. Exactly as if you did
printf("%d",printf("6"));
which 1st prints "6", then pass the result to the outer printf to print what the inner printf returned, that is 1)
In your second code, you do nothing to change a's value, and you ignore the result of printf.
Your examples aren't equivalent. To be equivalent, the second one should say a=printf(... everywhere. After which a will get assigned the number of characters printed, 1.
The conditional operator (e1 ? e2 : e3) is not a "short version of if condition", although it has some similarities with an if ... else construct. The conditional operator yields a value (which you assign to a in your first example); an if ... else construct does not have a value.
So, your first example assigns a value to a, because it is written in the form of an assignment statement; that value is the 1 returned by the call to the printf function. To get similar behaviour in your second example, as others have said, you need to also assign the value returned by printf inside the if ... else blocks.
Alternatively, to make the first case work like the second, you can skip the assignment and use the conditional operation to determine the argument that is passed to the printf call:
int main(void)
{
int a = 0;
printf(7 > 2 ? "6" : "4");
printf("%d", a);
return 0;
}

How are if statements in C syntactically unambiguous?

I don't know a whole lot about C, but I understand the basics and as far as I can tell:
int main() {
if (1 == 1) printf("Hello World!\n");
return 0;
}
and
int main() {
if (1 == 1)
printf("Hello World!\n");
return 0;
}
and
int main() {
if (1 == 1) {
printf("Hello World!\n");
}
return 0;
}
are all precisely syntactically equivalent. The statement is true; the string is printed; the braces are (apparently) optional.
Sometimes, especially here on SO, I see something like the following:
int main() {
if (1 == 1)
printf("one is one\n");
printf("is this inside the if statement??/who kn0WS\n");
return 0;
}
By the power vested in CodeGolf, I have been led to believe that C is whitespace-agnostic; the lexical analyser breaks the tokens up into their component parts and strips whitespace outside strings.
(I mean, the whole reason for the semicolons-on-every-statement-thing is so the parser can strip \n, \t, literal spaces and still know where each statement ends, right??)
So how is it possible to unambiguously parse the previous bit of code (or perhaps someone can come up with a better example of what I mean), if whitespace is to be disregarded?
If C programmers want to write in whitespace-dependent Pythonic syntax, why do they write C, and why is it taught wherever C is taught that it's okay to write lexically ambiguous (both to me, a programmer, and the computer) statements like this?
if (1 == 1)
printf("one is one\n");
printf("is this inside the if statement??/who kn0WS\n");
The second printf() should never execute inside the if statement.
The reason being that the previous line ends with a semicolon, which indicates the end of the if-block to execute.
(I mean, the whole reason for the semicolons-on-every-statement-thing
is so the parser can strip \n, \t, literal spaces and still know where
each statement ends, right??)
So how is it possible to unambiguously parse the previous bit of code
(or perhaps someone can come up with a better example of what I mean),
if whitespace is to be disregarded?
Parsing example:
if (1 == 1) // if - ( and ) - statements (or block) follow, skip all whitespace
// no { found -> single statement, scan until ; (outside quotes / comments)
printf("one is one\n"); // ; encountered, end of if-block
Without braces, only one statement belongs to the if-block.
But, as said already, it's a good habit to use braces. If you later add a statement (a quick temporary printf() for example), it will always be inside the block.
Special case:
int i = 0;
while(i++ < 10);
printf("%d", i);
Here printf() will only execute once. Mark the ; at the end of while().
In case of an empty statement, it's better to use:
while(i++ < 10)
;
to make the intention clear (or, as an alternative, an empty block {} can be used as well).
In C, an if statement takes exactly statement after the truth expression, regardless of indentation. Normally this statement is indented for clarity, but C ignores indentation. In any case, there is no amiguity in any of your examples.
What is ambiguous, in C and in many other languages, is the "dangling else". For instance, suppose you have a nested if statement with a single else after the second one. It could group as:
if (expr)
if (expr)
statement
else
statement
Or it could group as:
if (expr)
if (expr)
statement
else
statement
The only difference between these two is how they're indented, which C ignores. In this case, the ambiguity is resolved by using the first interpretation, i.e., the else statement binds to the nearest preceding if statement. To achieve the second interpretation, curly braces are needed:
if (expr) {
if (expr)
statement
}
else
statement
However, even in the first case, it's a good idea to include the curly braces, even though they aren't required:
if (expr) {
if (expr)
statement
else
statement
}
tl;dr The only ambiguity is in how difficult it is for a human to read. From the compiler's perspective, the syntax is perfectly unambiguous.
There are only two (compilable and syntactically acceptable) possibilities after an if statement:
Braces, as in
if(x) {
DoFoo();
}
// or
if(x) { DoFoo(); }
In this case, whatever is in the {...} will execute if the condition is met.
No braces, as in
if(x)
DoFoo();
// or
if(x) DoFoo();
In this case, only the next statement will execute if the condition is met.
You are correct that C is whitespace-agnostic. As a result, omitting the braces can lead to some tricky bugs. For example, in this code, DoBar() will execute whether or not the condition is met:
if(x)
DoFoo();
DoBar();
Inconsistent use of braces can also easily result in invalid code. For example, this looks valid (at a glance) from a human perspective, but it's not:
if(x)
DoFoo();
DoBar();
else
DoBaz();
None of the examples you posted are ambiguous from the compiler's perspective, but the no-braces versions are confusing from a human perspective. Leaving out the braces frequently leads to hard-to-find bugs.
Without braces it is just the next statement after the if. The whitespace does not matter
It is good practice and makes life easier to always use the braces. Good indentation as well. Code is then easy to read and does not lead to errors when people add/remove statements after the if
Readability is the only ambiguity in the statement:
if (1 == 1)
printf("one is one\n");
printf("is this inside the if statement??/who kn0WS\n");
The only time the first statement following the if(...) statement should execute, is if it is evaluated TRUE.
Braces, {...} help to remove readability ambiguities,
if (1 == 1)
{
printf("one is one\n");
}
printf("is this inside the if statement??/who kn0WS\n");
but the syntax rules are still the same.
Opinions vary, but I always choose to use braces.
Not using them is fine at the time code is written. But down the road, you just know someone will come along and add another statement under the first and expect it to be executed.
In general, in a statement or a loop with a single instruction, the curly brackets are optionals; instead, if you have two or more instructions you have to add them.
For example :
for(i = 0; i < 2; i++)
for(j = 0; j < 4; j++)
If(...)
printf(..);
else
printf(..);
Is equivalent to :
for(i = 0; i < 2; i++)
{
for(j = 0; j < 4; j++)
{
If(...)
{
printf(..);
}
else
{
printf(..);
}
}
}
As you may note this is more something related to indentation of the code. Personally I don't use curly brackets if I have a single instruction as doing that will make your code shorter and cleaner.
Another reason to use braces is that a simple typo can bite you hard:
#include <stdio.h>
int main(void) {
if (0 == 1)
printf("zero is one\n"),
printf("is this inside the if statement?? /who kn0WS\n");
return 0;
}
Look carefully...

assignment works as a condition

Consider the following Code,
int i;
while(i=0)
printf("Hello");
Now Generally speaking i=0 is an assignment and not a condition for while to check.
But the GCC compiler lets it go with a warning and even evaluates it correctly (does not execute the print statement).
Why? I usually would do with parenthesis for the truth value but my juniors feel that I am wrong and there is no real reason for the parenthesis in this!
EDIT: Zeroing down on the 'actual' doubt, Please consider the following test case
int callme(){
return 0;
}
int main(int argc,char*argv[]){
int c;
while(c = callme()){
printf("Calling...\n");
}
return 0;
}
The expression i = 0 does 2 things:
Has the side effect of storing o in i
Yields the value 0
I usually would do with parenthesis for the truth value but my juniors
feel that i am wrong and there is no real reason for the parenthesis
in this
It's usually a hint to the compiler meaning "I actually want this, I didn't forget a =, shut up".
For your specific case there's no reason to write if (i = 0): you already know what if (0) does. But it's pretty useful when used as:
if ((i = some_function()))
...
i=0 is always an assignment (unless you have it as part of int i = 0; where it is an initialization). But any non-void expression may appear inside the condition of a while loop and if it evaluates to non-zero, the body of the loop will be executed, and if it is zero, the body of the loop will not be executed.
The notation:
while (i = 0)
printf("Hello\n");
is always equivalent to:
i = 0;
There is very little justification for writing the loop at all.
People do write other expressions:
while (c = getchar())
...process EOF or a non-null character...
But that's usually a bug. It is more likely that you should be writing:
while ((c = getchar()) != EOF)
...process a character - possibly null...
or even:
while ((c = getchar()) != EOF && c != '\0')
...process a non-null character...
The first getchar() loop gets a warning from GCC; the latter two do not because of the the explicit test of the value from the assignment.
The people who write a condition like this:
while ((c = getchar()))
really annoy me. It avoids the warning from GCC, but it is not (IMNSHO) a good way of coding.
When you use an assignment operator such as
a=0;
You assign the value to 'a', and still return the number 0.
To test your question, I tried these lines of codes:
int a;
printf("%d", a=0);
and these lines displayed 0.
Then, I tested another set of codes:
int b;
printf("%d", b=15);
Here, the lines displayed 15.
So, if you do:
while(a=0)
{
printf("zero");
}
The (a=0) statement would return false, thus not displaying anything.
But if you do:
while(a=15)
{
printf("fifteen");
}
The "fifteen" will be displayed endlessly, because the statement (a=15) will return a non zero value, or 15, which is not false, not zero, thus it is true. :)
As cnicutar has told above the assignment also yields the value zero.
Some additional info:
It is a common coding mistake for people to omit an extra '=' whereby the comparison becomes an assignment.
An easy way to avoid this is to write the comparison as below, in which case even if a '=' is missed compiler will give an error
while(0 == i)
{
prinf("Hello");
}

exiting a while loop with a negative integer

I want to exit a while() when the user enters a negative number of any size. What kind of condition would I need at the start of the loop to get the loop to exit when the user enters a negative number?
Well, what is a negative number? It's a number (call it x) that is less than zero, or symbolically, x < 0. If x is less than zero, then this is true. If not, then it is false.
You can loop endlessly and break when this condition is met:
while (1) {
if (x < 0) {
break;
}
...
}
But I prefer to just use the opposite of that condition in the while loop itself:
while (x >= 0) {
...
While the condition is true, then the loop continues. When it is false (and your original condition is true, as these two are opposite), the loop breaks.
Use an if condition to know the number is less than 0 or not. And if yes, just use break statement inside it, which will bring you out of the loop. Learn more about break statement from MSDN.
int i = -1;
do
{
i = magic_user_input();
//simple enough? get a decent programming book to get the hang of loops
}
while(i > -1)
edit: sorry, my mistake: 'i' wasn't declared properly :) now it should be fine to use
Do not define your variable as unsigned variable. As suggested in other answers use if statement and break with if statement.
example:
int main(void)
{
int i;
while(1){
/*here write an statement to get and store value in i*/
if(i<0)
{
break;
}
/*other statements*/
return(0);
}
}

C exit function not doing what I thought it would

When I use a debugger I can tell the exit is not exiting the function. Am I using the exit function wrong? (i must be) how do I fix this?
int is_prime(int x,char array[]){
int divider = (x-1);
float test;
while(x>-1){
test = isdigit((x % divider)); //isdigit returns !0 if digit
if(divider == '1'){
return(1); //if divider reaches 1 then the number is prime
exit;
}
if(test == '0'){
return (0);//not prime
exit;
}
divider--;
}
}
The name of a function by itself (with no parenthesis after it) just gives you the address of a function without calling it. In C the most basic statement is an expression which is evaluated for its side effects, with the resulting value of the expression ignored. So a statement like exit; or 3; which has no side effects is legal but doesn't actually do anything and might as well be deleted. Some compilers will give you warnings about such meaningless statements, though you may have to turn on extra diagnostic warnings to get them. Using such options (such as -Wall for gcc) is a very good idea and will help you avoid some pitfalls like this.
You must call it:
exit(0);
Also, if you put it after return, it will never be called, since return returns from the function.
EDIT: And, as others have said, exit exits the program, so you probably don't want to use exit here.
Besides the bugs of returnand exit you have a bug also in the way you use ints and characters. isdigit is a function that is only applied to characters, giving true if a character is between '0' and '9', but one should know that the character notation in C is only a fancy way of writing a codepoint (ASCII most of the time). So when you write '1' in a C program, the compiler will see 49, if you write 'a' the compiler sees in reality 97. This means that isdigit return true for the values 48 to 57, probably not what you intended. In the line where you compare divider with '1', in reality you're comparing it with 49 (except on IBM mainframe, where '1' is 241)
Your loop is infinite, it depends on the value of x, but x isn't changed in the loop, so the condition in the while can never change.
EDIT: Here the corrected code
int is_prime(uint_t x)
{
uint_t divider;
if(x <= 3)
return 1;
for(divider = x-1; ; divider--) {
if(x % divider == 0)
return 0; //not prime
if(divider == 1)
return 1; //if divider reaches 1 then the number is prime
}
}
Read exit(3)'s manual.
The statement:
exit;
gives the following warning with GCC:
C:\temp\test.c:71: warning: statement with no effect
What happening is that you have an expression that evaluates to the address of the exit() function - but that expression doesn't actually do anything with that address. it's similar to if you had a statement like:
1 + 2;
It's valid C, but it has no effect on anything.
To call the function, as Thomas Padron-McCarth said, you have to have the argument list (even if they're empty for some functions):
exit(0);
exit exits the process, not the function. You want return.

Resources