return- and return! in C - c

While looking through puzzles and answers in the code golf Q&A section, I came across this solution for the longest and most obscure ways to return 1
Quoting from the answer,
int foo(void) {
return! 0;
}
int bar(void) {
int i=7;
while (i --> 0);
return-i;
}
The --> 'operator' is already well-known :), but I couldn't find any info on return! 0; and return-x; where I'm guessing x could be any variable
Do they really exist, and what do they mean? Does it have anything to do with precedence?

It's really the same idea as with -->. C compilers tokenize program text using a particular algorithm that makes
return-i
parse like
return -i
and
return! 0
parse like
return !0
All the same.

The ! and - are for the "second part of the operator", they don't have anything to do with return.
return-x; just returns the negated value of x.
return! 0; is return (!0);, nothing special.

The notation return! 0 can be interpreted as return (!0) which is basically return 1.
The other notation return -x where x is equal to -1 (as a result of while (x --> 0); is just return 1.

return!0; is the same as return (!0);, and !0 == 1.
For second one, return-i returns 1 because i==-1 at that point (after while loop decrements it to -1), and return-i same as return (-i), or return 1.

The spacing may be throwing you off:
return !0;
is basically making 0 non-0, or "true", 1.
"-->" is not "an" operator, it is 2 operators: decrement&save-later "--" and compare ">"
i-- > 0, or see if i is still greater than 0 then decrement it. What it's usage is doing is decrementing i from 7 until it becomes 0 (and decrements after the compare making a negative number, which the first occurrence would be -1)
return -i;
is just turning that -1 into a positive 1

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

Confusion with operator '!' in c

I've seen the operator ! being used in multiple places differently and I still don't get how it actually works. My basic understanding is it reverses the value from true to false and vice versa. If it reversed to true the statement triggers. Let's take an example.
int main(void)
{
int a = 5;
if (!(a == 6))
{
printf("unlike\n");
}
if (!(a == 5))
{
printf("like\n");
}
}
In the code above since a is 5 it ends up printing "unlike" because the false statement that a is 6 got reversed. Now let's take another example.
int main(void)
{
string i = "abc";
string j = "cab";
string k = "abc";
if (!strcmp(i, j))
{
printf("unlike\n");
}
if (!strcmp(i, k))
{
printf("like\n");
}
}
The string type has been taken from the cs50.h header and strcmp from string.h. strcmp returns value 0 if the two strings are alike and if unlike depending on the alphabetical order returns a positive or negative value. Now if we follow the logic in the previous example, since i and j are unlike, and false it should be reversed to true and unlike should be the output. But I tried running the code and the result was like.
I am confused. Can anyone please explain this to me clearly? Feel free to use other examples too. I could always get away with not using ! but I just want to learn what it is and how to properly use it.
A boolean in C is an integer with zero for false and non-zero for true.
strcmp returns 0 when the compared strings are identical and a non-zero value depending on the difference otherwise. Therefore, strcmp(i,k) is seen as "false". The ! then changes this to "true", which leads to your current output.
In the first case a = 5. then if (!(a == 6)); here a = 6 is not true (false), so it's something like this. if (!(false)) it means if (true). That's why it prints "unlike".
strcmp(i, j) returns 0 if the strings i and j match; otherwise, it will return a non-zero value. In your case,
(!strcmp(i, j))
Here i and j are not equal so strcmp will return a non-zero value because i != j. So !(1) means not(1) means 0, so the if condition is false because of zero. Therefore it'll not execute the printf("unlike\n") line.
(!strcmp(i, k))
Here i and k are same so strcmp will return 0. !(0) means not(0) = 1 so the if condition is true. It will execute the printf("like\n") line.

What does the exclamation point in if (!strcmp() ... do?

Can someone explain what the exclamation point in the if statement does (i.e. !strmcp)?
string names[] = {"EMMA", "RODRIGO", "BRIAN", "DAVID"};
// Search for EMMA
for (int i = 0; i < 4; i++)
{
if (!strcmp(names[i], "EMMA"))
{
printf("Found\n");
return 0;
}
}
printf("Not found\n");
return 1;
For an if statement, if the expression evaluates to 0, then the block of code following the if statement is not executed. Any other value (positive or negative), will result in executing the code block. The function strcmp uses 0 to say that strings are equal because less than 0 is used to differ from greater than 0.
So in this code, we want printf("Found\n"); to be executed when the strings are equal. Since strcmp results in 0, we need to negate the value so that it becomes 1 which will result in executing that code block.
strcmp() returns 0 if the strings are identical, so you need to negate it, if you use it in an if clause to assert a true statement.
If your clause is if(0), the code inside the condition will not be executed.
For completion, it returns negative if the first different character found is lower in the first string, for instance:
first parameter string: "abca"
second parameter string :abcd"
This will return negative. If it's the other way arround it will return positive.
Also, string is not usually used in C (I refer you to Jonathan Leffler's commment), you can use char*:
char *names[] = {"EMMA", "RODRIGO", "BRIAN", "DAVID"};
Unary operator ! is called the logical NOT operator (cf., for example, this definition at cppreference.com). ! expression returns 1 if expression evaluates to 0, and it returns 0 if expression evaluates to anything else but 0.
So the condition in if (!0) gives 1; this means, the condition is met and the if-block is entered. It has the same meaning as if(0==0)
Consequently, the meaning of
if(!strcmp(names[i], "EMMA"))
in your code is exactly the same as
if(0==strcmp(names[i], "EMMA"))
And you already know when strcmp returns 0...
The exclamation point is the C's boolean negation character.
It means give me the boolean opposite of the value. A boolean is either true or false, which are 1 or 0 in the C Language.
In C, if statements execute their conditional statements if the argument is true.
if (a) means if a is true (i.e. non-zero)
if (!a) means if a is false (i.e. 0)
Therefore:
if (a) is the same as if (a != 0)
if (!a) is the same as if (a == 0)
Sometimes you'll see code that uses two exclamation points in a row "!!"
For example:
int a = !!b;
That ensures a will be ONLY 0 or 1, regardless of what the value of b is.
If b is ANY non-zero value, the ! operator will treat it as though it is true true, which it treats as being the same as 1
So:
!0 == 1
!1 == 0
!52 == 0
!25692 == 0
The second ! does the boolean inversion again, so:
!!0 == 0
!!1 == 1
!!52 == 1
!!25692 == 1
In C any non zero value is considered ad the logical truth, zero i considered as logical false. ! is a logical negation. So !0 (not false) will be the truth and if(!strcmp(str1,str2)) {statements} statements will be executed when str1 will be same as str2

Working of Nested IF-Else Without the Braces

Can someone please explain me the working of Nested If-Else Statements written WITHOUT the Curly Braces.
I want to understand why Below Programme isn't giving me any output.
I've checked for all the 4 possibilities.
(Outer-If, Inner-If)::(True, True),(True, False),(False, True),(False, False).
I'm editing with CodeBlocks,using gcc compiler on Windows.
int main()
{
int n=0,m=0;
if ( n > 0 )
if ( m > 0 )
printf("Inner-If Condition satisfied.");
else
printf("Inner-If condition not satisfied. ");
return 0;
}
Thank You.
They work as-if there was a curly brace around the following statement. In your case then:
if ( n = 0 ){ // ToDo - did you mean `==`, `n = 0` is `0`.
if ( m = 0 ){ // ToDo - ditto.
printf("True");
} else {
printf("False");
}
}
In your case I think the bewilderment stems from your using = rather than ==.
The if-else ambiguity is solved by defining that an ambiguous else belongs to the nearest if.
The parser will see an ambiguity, however, the parser has ben adapted to solve the ambiguity as described above (e.g. yacc).
Note: the reason your program does not give any output is because n=0 (an assignment) results in n being zero and so the test becomes false, so the branch is not taken and the return is executed.
n = 0 is an assignment in C. It assigns n the value 0. Assignments also evaluate to the value that is assigned, so here, to 0, which is in a boolean context false -- so your outer if is always false.
To compare two values, use == instead, which evaluates to 1 (true) on equality, 0 (false) on inequality. *)
Your assumption about if and else was correct, the reason you don't see output is just your wrong attempt at comparing values.
A good compiler will warn you of such typos. E.g. with gcc, enable a reasonable set of warnings with -std=c11 -Wall -Wextra.
*) as a side note, in a boolean context, a zero value is false and any other value is true, so you could also write the code like this (! is logical not, inverting true and false):
if (!n)
if (!m)
// ...
Whether this is good style depends on who you ask. I personally like to write it this way if 0 semantically represents the lack of a value, or if the variable is already meant as a boolean value. Then "if not n" sounds kind of natural.
Use == inside if Statement. such as below mentioned code will work.
if ( n == 0 )
if ( m == 0 )
printf("True");
else printf("False");

Difference between return 0 and return 1

My professor posted
int main(int argc, char **argv)
{
// enter code here
printf("Test 1: trying odd(3) AND even(2)...\n");
printf("%d\n", odd(3) && even(2));
printf("Test 2: trying odd(3) OR even(2)...\n");
printf("%d\n", odd(3) || even(2));
printf("Test 3: trying odd(4) AND even(7)...\n");
printf("%d\n", odd(4) && even(7));
printf("Test 4: trying odd(4) OR even(7)...\n");
printf("%d\n", odd(4) || even(7));
return 0;
}
int odd(int n)
{
printf("in odd!\n");
return n % 2 == 1;
}
int even(int r)
{
printf("in even!\n");
return r % 2 == 0;
}
as an assignment asking why lines 2 and 3 only return in odd! but 1 and 4 return in odd! and in even! I'm unsure as to why as I don't know the difference between the Return 1 and Return 0 commands. From what I can gather Return 1 will always return the value (in this case in odd!) but return 0 will only return it if it satisfies a certain condition?
Also: does the code int length(char *name,int start,double finish): return the length of a word in characters as a real number?
Thanks in advance to anyone that decides to help me.
This is called "Short-circuit evaluation".
...in which the second argument is executed or evaluated only if the first argument does not suffice to determine the value of the expression...
Therefore, you have to figure out what will these two functions odd and even return:
odd(): If n % 2 == 1 , return 1, otherwise 0
even(): If n % 2 == 0 , return 1, otherwise 0
And in the main() function,
odd(3) AND even(2): odd(3) return 1, and check the return value of even(2), therefore the even() is called.
odd(3) OR even(2): odd(3) return 1, because of 'short-circuit evaluation', it doesn't need to check the even(2), therefore the even() isn't called.
odd(4) AND even(7): odd(4) return 0, because of 'short-circuit evaluation', it doesn't need to check the even(7), therefore the even() isn't called.
odd(4) OR even(7): odd(4) return 0, and check the return value of even(7), therefore the even() is called.
when evaluating a logical expressions, it checks the condition one by one and whenever the whole expression is known (whatever the remaining are) it stops evaluating them.
Example
unsigned char a = 1; // true
unsigned char b = 0; // false
case 1
if (a && b) printf("Yes");
check a: yes it is true
check b: no it is not true
Result: the expression is wrong and it doesn't print Yes
case 2
if (a && !b) printf("Yes");
checks a: yes it is true
checks b: yes it is false
Result: the expression is right and it prints Yes
case 3
if (a || b) printf("Yes");
checks a: yes it is true
checks b ?!!! WHY? no need to check b since the whole expression result is known only by checking a, do you agree?
Result: checks aand print Yes without even checking b
Project that on your code now ;)
Return 0; - the function returns 0.
Return 1; - the function returns 1.
In your case odd function returns 1 when number (n) is odd and 0 when the number is even.
This is done by "asking" if the reminder when dividing by 2 equels 1.
Also even function returns 1 when number (r) is even, and 0 when the number is odd.
This is done by "asking" if the reminder when dividing by 2 equels 0.
In your main function, and (&&) and or logical operations are done, on the results of the return values of odd and even functions.
Example:odd(3) return 1, even(2) return 1 then 1&&1 equals 1 (the result).
The logical Boolean algebra operators AND and OR (&& and ||) in C operate with an optimization known as short-circuit evaluation.
This is how the optimization works.
Imagine that you came up with a rule for yourself:
You will only date someone if they own a cat AND a dog AND a fish.
Now imagine you start talking to someone that you may be interested in dating. They say:
Well, I have a cat, I don't have a fish, but I do have a dog.
When did you stop paying attention to what they said? As soon as they said that they didn't have a fish, because as soon as they said that, they broke your "AND" rule. So, the rest of the sentence is completely irrelevant. This is short-circuiting AND.
Now imagine that you changed your rule:
You will only date someone if they own a cat OR a dog OR a fish.
Now imagine you start talking to someone that you may be interested in dating. They say:
Well, I don't have a cat, I have a fish, and I don't have a dog.
When did you stop paying attention to what they said? As soon as they said that they had a fish, because as soon as they said that, they satisfied your "OR" rule. So, the rest of the sentence is completely irrelevant. This is short-circuiting OR.
Short-circuit evaluation is a performance optimization for evaluating logical expressions.
In your example, the even() function returns true if the number passed to it is even, and the odd() function returns true if the number passed to it is even. Otherwise these functions return false. Look at each of the Boolean expressions and notice when short-circuit evaluation must occur.
There's also another way to test for even values for integral types.
int IsOdd(int x) { return (x & 1); }
int IsEven(int x) { return !(x & 1); }
If the least-significant bit is set, the number is odd. If not, it's even. This simply tests that bit. Just throwing this out there so you can eliminate the modulus operation... it's another option. Not an answer to your question, but I can't comment so...
As we know 0 indicates false-ness, 1 indicates true-ness. And the return part tells the compiler that the function must return the evaluated result to the caller module.
So, a return 1 means signal the caller module about a successful execution of the called module (with the aid of a Non-Zero quantity i.e. 1)
whereas,
return 0 presents a flag showing that there was some error/anomaly that led to the termination of the called module. So, in this case stderr shall be used to give details about such error.

Resources