C assignments in an 'if' statement - c

I came across this line of code written in C that confuses me coming from a JavaScript background.
short s;
if ((s = data[q]))
return s;
Is this assigning s to data[q], and if it equals true/1, return s?

Yes, an assignment...well assigns...but it's also an expression. Any value not equalling zero will be evaluated as true and zero as false.
it would be the same as
if ((s = data[q]) != 0) return s;

Your code is assigning data[q] to s and then returns s to the if statement. In the case when s is not equal to 0 your code returns s otherwise it goes to the next instruction.
Or better said it would expand to the following:
short s;
s = data[q];
if (s != 0)
return s;

Basically C evaluates expressions. In
s = data[q]
The value of data[q] is the the value of expression here and the condition is evaluated based on that.
The assignment
s <- data[q]
is just a side-effect.
Read this [ article ] on sequence points and side-effects

Related

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

Can we assign a value inside the if statement?

#include <stdio.h>
void main()
{
int x = 0;
if (x = 0)
printf("It's zero\n");
else
printf("It's not zero\n");
}
Why is the statement if (x = 0) not an error? Can we assign a value like that in an if statement? Why is it not generating an error, and why is the else statement getting executed?
Yes, it is allowed to assign the value inside the if statement. This is very handy, among other things, when you want to call the function and check it's return for error:
int rc;
if ((rc = check())) {
// here rc is non-zero, often an indication of a failure
}
Note how I've put an extra pair of parenthesis around my assignment - since it is such an omnipresent source of confusion, compilers are usually warning about assignement in the if block, assuming you might have made a typo. Extra pair of parenthesis makes it clear for compiler that this is what I intended.
By the way, there is no special exception crafted here, validity of this syntax stems from general C grammar - an assignment operator evaluates to assigned value.
Yes, this is a perfectly valid syntax, there is no reason to disallow this.
Quoting C11,
[...] An
assignment expression has the value of the left operand after the assignment. [...]
So, the value which is stored in the LHS operand, would be used for the if statement condition evaluation.
In your case, the variable x holds the value 0 after the assignment, and if (0) is FALSY, that's why the else block gets executed.
However, most of the time, this syntax is used wrongly, instead of the comparison. That's why most of the compilers emit a warning message on this construct.
warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if (x = 0)
^
If you're sure what you're doing, you can wrap the if condition with an assignment expression in an additional pair of parenthesis, and you'll be good to go.
In C, the only requirement for an if statement is that it contains an expression. The truth of the statement is based on whether or not the expression evaluates to zero.
The assignment operator also evaluates to the assigned value, so if(a = 0) would be false, whereas if(a = x) where x != 0 would be true.
Since the assignment operator is an expression, it is acceptable to place in an if statement, though a frequent beginner mistake is to use the assignment operator where they intended to use the equality test operator ==.
One way you can avoid this is mistake is, if either side of the comparison is an r-value, put that on the left, so that if you ever accidentally use = where you meant ==, you will get a compilation error. Compare:
if(p = NULL) // Valid syntax
...
if(NULL = p) // Syntax error
...

Pre-Processor C Macro Syntax

I am trying to understand the Pre-Processor syntax. Its really simple line of code that either returns "ON" or "OFF". However I am utterly confused as to what exactly the condition is?
I understand C's conditional statement as follows:
? x : y
If Condition ? return - replace? x : or y either way this line of code is as follows:
#define ONOFF(a) ((a) ? "ON" : "OFF")
I don't understand what condition must be met here? Is the condition that a has to be something other than null?
True and Flase can be more perfectly presented as 1 or 0 . As I can see you have declared
#define ONOFF(a) ((a) ? "ON" : "OFF")
Your condition here is (a), which istrueif the value ofa is non zero and false if ais 0
Which means in your program, if you write
int a=1;
char *str;
str=ONOFF(a);
The substitution which takes place is
int a=1;
char *str;
str=((a) ? "ON" : "OFF")// here a=1
Since here a is 1 and
1 is true and str gets the value ON. If a were 0, then str would get the value OFF
The condition is that a has to evaluate to true. In c, that means that a must be an expression that is non-zero.
If a is a pointer type, NULL is false and any other value is true.
If a is an integer type, 0 is false and any other value is true.
If a is a floating point type, 0 is false and any other value is true.
If a is a struct or a void type you will get a compile error.
To add a bit of context here, the first operand of the conditional operato has to be of scalar type. Now, from chapter ยง6.2.5, of C11,
Arithmetic types and pointer types are collectively called scalar types.
So, for the conditional expression,
any non-zero value gets evaluated as TRUE and zero (0) is evaluated as FALSE.
(In case of pointers) a NULL is FALSE, any non-NULL is TRUE.
Preprocessor macros do textual substitution, so a is not a variable -- it's just a placeholder for whatever text is in the parentheses when the macro is used.
You could use it for checking pointers are not null like this:
printf("%s\n", ONOFF(ptr));
printf("%s\n", ONOFF(ptr != null)); // This is the same
Or any other type of condition you like:
printf("%s\n", ONOFF(a > b));
printf("%s\n", ONOFF(a && b));
printf("%s\n", ONOFF(a == 1 || c == 4));
printf("%s\n", ONOFF(somefunction() != 0));
printf("%s\n", ONOFF((a == b && c == d) || (a == c && b == d));
printf("%s\n", ONOFF(my_bool_value));

Assigning value in while loop condition

I found this piece of code on Wikipedia.
#include <stdio.h>
int main(void)
{
int c;
while (c = getchar(), c != EOF && c != 'x')
{
switch (c)
{
case '\n':
case '\r':
printf ("Newline\n");
break;
default:
printf ("%c",c);
}
}
return 0;
}
I'm curious about expression used as condition for while loop:
while (c = getchar(), c != EOF && c != 'x')
It's quite obvious what it does, but I've never seen this construction before. Is this specific to while loop? If not, how does parser/compiler determine which side of comma-separated expression returns boolean value for while loop?
The comma operator is a binary operator that evaluates its first operand and discards the result, it then evaluates the second operand and returns this value.
It is also a "sequence point", which means that all side effects will be calculated before the next part of the code is executed.
The comma operator is a weird beastie until you get to understand it, and it's not specific to while.
The expression:
exp1, exp2
evaluates exp1 then evaluates exp2 and returns exp2.
You see it frequently, though you may not realize it:
for (i = j = 0; i < 100; i++, j += 2)
You're not actually using the return value from "i++, j += 2" but it's there nonetheless. The comma operator evaluates both bits to modify both i and j.
You can pretty well use it anywhere a normal expression can be used (that comma inside your function calls is not a comma operator, for example) and it's very useful in writing compact source code, if that's what you like. In that way, it's part of the family that allows things like:
while ((c= getchar()) != EOF) {...}
i = j = k = 0;
and so on.
For your specific example:
while (c = getchar(), c != EOF && c != 'x')
the following occurs:
c = getchar() is executed fully (the comma operator is a sequence point).
c != EOF && c != 'x' is executed.
the comma operator throws away the first value (c) and "returns" the second.
the while uses that return value to control the loop.
In many languages the comma is an operator that always results in the value of the second operand. The operands are evaluated sequentially from left to right.
Pseudo-code:
a = 10
print a = 7 + 8, a * 2
Note: print is considered a statement that does not take arguments, so what comes after is considered the single expression a = 7 + 8, a * 2.
Executed like this:
First line
put 10 in a
Second line
evaluate 7 + 8 (15)
put evaluated value (15) in a
evaluate a * 2 (30)
evaluate , operator with operands 15 and 30:
always value of second operand (30)
print evaluated value (30)
To expand a bit on the other answers, in this code:
EXPRESSION_1 , EXPRESSION_2
EXPRESSION_1 is first evaluated, then there is a sequence point, then EXPRESSION_2 is evaluated, and the value of the whole thing is the value of EXPRESSION_2.
The order of operation guarantee and the sequence point are both important to the code you quoted. Together, they mean that we can be certain that the getchar() function gets called and the value of variable c is fully updated before the value of c is tested.
The comma is an operator. It returns the value of the right hand expression by default. The order of evaluation is guaranteed to be left first and then right.
UPDATE (reply to Pax's comment):
Just like most operators, it can be overloaded for user defined types:
#include <iostream>
#include <string>
using namespace std;
enum EntryType { Home, Cell, Address };
class AddressBookEntryReference {
public:
AddressBookEntryReference(const string& name, const EntryType &entry)
: Name(name), Entry(entry) { }
string Name;
EntryType Entry;
};
AddressBookEntryReference operator,(const string& name, const EntryType &type) {
return AddressBookEntryReference(name, type);
}
class AddressBook {
string test;
public:
string& operator[](const AddressBookEntryReference item) {
// return something based on item.Name and item.Entry.
// just to test:
test = item.Name;
return test;
}
};
int main() {
// demo:
AddressBook book;
cout << book["Name", Cell] // cool syntax!
<< endl;
}

Resources