lvalue required as left operand of assignment - c

Why am I getting
lvalue required as left operand of assignment
with a single string comparison? How can I fix this in C?
if (strcmp("hello", "hello") = 0)
Thanks!

You need to compare, not assign:
if (strcmp("hello", "hello") == 0)
^
Because you want to check if the result of strcmp("hello", "hello") equals to 0.
About the error:
lvalue required as left operand of
assignment
lvalue means an assignable value (variable), and in assignment the left value to the = has to be lvalue (pretty clear).
Both function results and constants are not assignable (rvalues), so they are rvalues. so the order doesn't matter and if you forget to use == you will get this error. (edit:)I consider it a good practice in comparison to put the constant in the left side, so if you write = instead of ==, you will get a compilation error. for example:
int a = 5;
if (a = 0) // Always evaluated as false, no error.
{
//...
}
vs.
int a = 5;
if (0 = a) // Generates compilation error, you cannot assign a to 0 (rvalue)
{
//...
}
(see first answer to this question: https://stackoverflow.com/questions/2349378/new-programming-jargon-you-coined)

You cannot assign an rvalue to an rvalue.
if (strcmp("hello", "hello") = 0)
is wrong. Suggestions:
if (strcmp("hello", "hello") == 0)
^
= is the assign operator.
== is the equal to operator.
I know many new programmers are confused with this fact.

Change = to ==
i.e
if (strcmp("hello", "hello") == 0)
You want to compare the result of strcmp() to 0. So you need ==. Assigning it to 0 won't work because rvalues cannot be assigned to.

You are trying to assign a value to a function, which is not possible in C. Try the comparison operator instead:
if (strcmp("hello", "hello") == 0)

I found that an answer to this issue when dealing with math is that the operator on the left hand side must be the variable you are trying to change. The logic cannot come first.
coin1 + coin2 + coin3 = coinTotal; // Wrong
coinTotal = coin1 + coin2 + coin3; // Right
This isn't a direct answer to your question but it might be helpful to future people who google the same thing I googled.

if (strcmp("hello", "hello") = 0)
Is trying to assign 0 to function return value which isn't lvalue.
Function return values are not lvalue (no storage for it), so any attempt to assign value to something that is not lvalue result in error.
Best practice to avoid such mistakes in if conditions is to use constant value on left side of comparison, so even if you use "=" instead "==", constant being not lvalue will immediately give error and avoid accidental value assignment and causing false positive if condition.

Related

Trouble understanding increment operators with arrays in C

I'm having trouble wrapping my head around a concept in C regarding the use of the operator ++ and arrays. I know enough that ++ will increment a value, but I'm running into a code snippet that does not make any sense to me:
while((c = getchar()) != EOF)
{
if(c < NUM_CHARS)
{
thisval = ++freqarr[c];
if(thisval > maxval)
{
maxval = thisval;
}
}
the line thisval = ++freqarr[c]; does not make a lot of sense to me.
Does it mean that thisval adds an additional index or value to the array?
I'm still new to C, so I'm not sure if this is common in C or not, if it's not or looked down upon, please let me know.
Prefix ++ has lower precendence than [], see https://en.cppreference.com/w/c/language/operator_precedence. So this is equivalent to thisval = ++(freqarr[c]);. It takes the cth element of the array, and increments that element, then assigns the new value to thisval. Just like:
freqarray[c] = freqarray[c] + 1;
thisval = freqarray[c];
I presume that c is defined as an int and freqarr is defined as an array. (It's generally best to include a Minimal, Reproducible Example in your question).
The prefix ++ operator increments an object and yields the incremented value. freqarr[c] is an object. The fact that it happens to be an element of an array is not relevant here. It works the same way as it would if it were applied to a simple named variable.
Note that the indexing operator [] binds more tightly than ++, so the expression ++freqarr[c] is equivalent to ++(freqarr[c]).
The prefix ++ operator increments its operand, and the resulting expression has the incremented value.
So this line does two things:
It increments the value of freqarr[c] which is a member of an array
It assigned the incremented value of freqarr[c] to thisval

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

C assignments in an 'if' statement

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

Precedence of arr[x++]--

I am confused on how to parse precedence of operations in C. the line
countArray[*string++]--
Is executing how I want it to, but I don't understand the steps that result in countArray[*string]-- being evaluated before *string++.
My research on C precedence and binding didn't provide answers that relate to this case, and I'm wondering about general rules for post/pre-increment and post/pre-decrement when in combination with other post/pre - crements.
How does C know to evaluate it this way?
void discountChars(char* string, char** countArray)
{
int test;
while(*string) {
test = *string;
//why is countArray[*string]-- evaluated before string++ is incremented?
countArray[*string++]--;
printf("countArray[%d] = %d\n", test, countArray[test]);
}
}
You can break this:
countArray[*string++]--;
down into this:
char index = *string; // get char from `string` into temporary index
string++; // increment `string`
countArray[index]--; // decrement `countArray` value at given index
and then it should be clearer what's going on.
As it has been stated many times, precedence has no connection to the order of evaluation. The only thing in C language that can affect order of evaluation is sequencing. Precedence has nothing to do with it.
It is also unclear where you got the strange idea that "countArray[*string]-- is being evaluated before *string++". This is simply impossible. The expression in [] will always be evaluated first, since its result is required to perform the element access (i.e. sequenced before the element access). Which means that the opposite is true: *string++ is evaluated before countArray[*string]--.
So, the sequence of steps here is
Evaluate *string++. The result of this expression is the original value of *string. Let's designate it tmp.
This expression also "schedules" a side-effect - increment of string. But this increment does not have to happen right now.
Evaluate countArray[tmp]--. The result of this expression is the original value of countArray[tmp]. This result is immediately discareded.
This expression also "schedules" a side-effect - decrement of countArray[tmp]. But this decrement does not have to happen right now.
Complete the evaluation of the full expression . If any of the above side-effects are still pending, complete them right now.
For example, one possible evaluation schedule might look as follows
char tmp = *string; // subexpression inside `[]`
countArray[tmp]; // full expression, result discarded
countArray[tmp] = countArray[tmp] - 1; // side-effect
string = string + 1; // side-effect
Another possible evaluation schedule is
char tmp = *string; // subexpression inside `[]`
string = string + 1; // side-effect
countArray[tmp]; // full expression, result discarded
countArray[tmp] = countArray[tmp] - 1; // side-effect
It can even be evaluated as
string = string + 1; // side-effect
char tmp = *(string - 1); // subexpression inside `[]`
countArray[tmp]; // full expression, result discarded
countArray[tmp] = countArray[tmp] - 1; // side-effect
Precedence controls groupings of operators and operands, not order of evaluation.
The expression *string++ must be evaluated before it can be used as an array subscript; however, the side effect of updating string may happen after the larger expression has been evaluated. The following sequence of events is allowed:
t1 <- *string
countArray[t1] <- countArray[t1] - 1
string <- string + 1
Then again, so is the following:
t1 <- *string
string <- string + 1
countArray[t1] <- countArray[t1] - 1

C pointer sum "not working"

I do not understand what is the point in the else sentence *nombre=(*nombre)++.
Output shows "fernando" and what i thought it was going to show was "ffsoboep" because of the sum. But it seems that *nombre=(*nombre)+1 is different to *nombre=(*nombre)++;
My question is why is that happening? how does "++" operator works in that case. Thanks.
void recursiva (char * nombre)
{
if (*nombre != '\0')
{
recursiva(nombre+1);
if(*nombre > 'A' && *nombre < 'Z')
{
*nombre=*nombre | 32;
}
else
{
*nombre=(*nombre)++;
printf("%c \n",*nombre);
}
}
}
int main()
{
char nombre[]="Fernando";
recursiva(nombre);
printf("%s",nombre);
}
(*nombre)++
doesn't mean the same thing as
*nombre + 1
It means "return the original value of *nombre, with the side effect of increasing *nombre's value by 1". Note that when exactly the value of *nombre increases is rather vague; while it happens after the value of (*nombre)++ is computed, it might happen before, after, or during the assignment to *nombre, with unpredictable results.
If you want to increase the value of *nombre, you don't need to assign the value of (*nombre)++ back to *nombre, and in fact, trying to do so is undefined behavior. As a first approximation, the program is allowed to do anything, up to and including making demons fly out your nose. Just use ++:
(*nombre)++;
or += 1:
*nombre += 1;
I ran your code and actually got "ffsoboep".
If you see that in other compilers you get "fernando", I believe that the following point is not defined in the standard:
*nombre=(*nombre)++;
This is post increment. The value of (x++) is the value of x before the increment (i.e., x == x++ is true).
The question is when does the increment is done.
If the increment is done immediately or after the evaluation of the right side of the = expression, then you first increment the value, and then re-assign the value of the expression (*nombre)++ (which is the value before the increment) to the already incremented *nombre.
If the increment is done, after all the expression is evaluated, then you first assign the (same) value to *nombre, and only then increment.
I think this is not defined in the standard, and therefore - you might see different behaviours. I encountered similar case in the past.

Resources