Are these two expressions in C equal? - c

Is a*=b; the same as a*a=b;, and if not, what is its equal?
I'm little confused because I keep getting wrong answer on this test:
#include<stdio.h>
main ()
{
int i, j, a=1, b=3;
for(j=1; j<3; j++)
a*=b;
b++;
printf("a=%d", a);
}

a *= b; is equivalent to a = a * b;.
*= is a compound assignment operator - you can read more about them here: http://tigcc.ticalc.org/doc/opers.html#assign
There's also a good explanation of this and other operators here:
http://www.tutorialspoint.com/ansi_c/c_operator_types.htm

What is the "wrong" answer you're getting, and which one do you expect? Note that b++ is outside of the loop; use { and } to create a block for the loop's body if you want it executed within the loop
for(j=1; j<3; j++) {
a*=b;
b++;
}
Other than that, to answer your actual question: What Eoin said, and in this context take a look at what an lvalue and rvalue is.

a*=b is equivalent to a = a*b.

a *= b;
compiles.
a * a = b;
does not compile, giving something like this:
error: lvalue required as left operand of assignment
From the above we can conclude:
No, the both expressions are not equal
As the second expression above does not compile you either have no equivalent or endlessly.
For the first expression there are (at least) two equivalents:
a = a * b;
or
a = b * a

First) You need to in-close the for loop with {}
int j;
for(j=1; j<3; j++){
printf("like this");
}
Second) a*=b is the same as a=a*b. a*a=b is trying to store the value of b in a variable called a*a.
int a*a;
int b;
a*a=b;
Which won't work because a*a isn't a valid variable name.
Lastly) The result of your code, how you have it written (once you fix the for loop with {}) should be:
a=3a=12

Related

Expressions and for loops in C

Is this correct way of assigning an expression to a variable?
int a == ( i<3 );
And I want to use a for loop like this
for(i=0;a; i++)
The assignment operator is =. So the correct way to assign an expression to a variable is
int a = i < 3;
More accurately, this assigns the value of the expression to a variable. It does not assign the expression itself to the variable. This means that the expression is evaluated immediately. When you do
for(i=0;a; i++)
The value of a will never change even though i does.
The idiomatic way of writing for loops is to write the boolean expression inline:
for(i=0;i<3; i++)
If you have some more complicated calculation to determine when a loop should end, then you can write a function for the calculation. For example:
int condition(int i) {
return i < 3;
}
Now you can write the for loop as
for (i = 0; condition(i); i++)
You can use macros like following
#include <stdio.h>
#define a(i) i < 3
int main(void) {
for(int i =0; a(i); i++) {
printf("%d\n",i);
}
return 0;
}
Output
0
1
2
EDIT
As others said macro is not a good idea when the condition is large. In that case you can make a separate function for the complex logic and use that in your for loop condition part. Like following:
int a(i) {
return i < 3; // Your condition. It may be even more complex as per your requirement.
}
Then you can use that function in your for loop in the following way:
for(int i =0; a(i); i++ ){...}
You cannot do that, why would you even want to? Can you give me an example, where this would be useful? Just curious, maybe we find better solution :)
Also, you can read more about loops at http://en.cppreference.com/w/cpp/language/for

Assign and compare in a single statement in C

How can I convert the following code to a single line?
int *i;
i = some_func_ret_int_ptr();
if(!i)
{
// Do something
}
// Will use 'i' later
I want to do something like:
if((i=some_func_ret_int_ptr) && !i)
{
// Do something
}
// Will use 'i' later
But I am wasting one comparison here. Is there a better way to do it?
All I want is assignment and comparison in the if and compare only i.
With C, this is as far as you can golf it:
int *i;
if(!(i = some_func_ret_int_ptr()))
{
// do something
}
// Will use i later
In addition to what is suggested in other answers, you can also do it as
if (i = some_func_ret_int_ptr(), !i)
{
// Do something
}
It is a literal implementation of what you had originally, with the statement sequence replaced with an expression sequence separated by the , operator.
It does not make much practical sense, though.
You can do
if(!(i = some_func_ret_int_ptr()))
{
...
}
What happens in this code, in order, is:
The return value of some_func_ret_int_ptr() is assigned to i
The statement !i is checked
If i == 0 what's inside the if gets executed, otherwise it will not
Clean and readable:
int * i = some_func_ret_int_ptr();
if (!i) { /* ... */ }
An option not mentioned yet is:
if ( NULL != (i = some_func()) )
Using the explicit comparison against NULL makes it very easy to read the intent of this code. Especially considering that your function probably won't have ret_int_ptr in its name.
Using the #include <ctype.h> standard library, to get the toupper(char) function, we can write the following function:
void StringToUppercase(char* str)
{
for (int i=0; (str[i] = toupper(str[i])) != 0; i++); // No for-loop body!
// The expression "(str[i] = toupper(str[i]))" executes first and then returns str[i]
}
so that the statement (str[i] = toupper(str[i])) != 0; both assigns a char and checks to see if it is '\0' or not.
The way this works is that part of the C language specifies that assignment expressions have the value of the lefthand expressions after the assignment. For example, with ints, consider the following code snippet:
int x = 5;
int y = x = 8;
// Assignment operators (= += <<=) have right-to-left associativity.
// The expression `(x=8)` returns the value 8, after it has been executed
int z = x != y; // Comparisons have greater (tighter) precedence than assignment
printf("(x, y, z) = (%d, %d, %d)\n", x, y, z); // prints (8, 8, 0)
Same as M.M's answer, but I would go with:
if ((i = some_func_ret_int_ptr()) != NULL)
As it makes the execution order clearer.

lvalue required as left operand of assignment

I am not able to compile this program.can anyone tell me tell me where i am going wrong.
int i = 8, j, k;
++i = ++j = ++k = 8;
printf("\n %d \t %d \t %d",i,j,k);
it is giving the error
error : lvalue required as left operand of assignment
The segment ++i is not an lvalue (so named because they generally can appear on the left side of an assignment).
As the standard states (C11 6.3.2.1):
An lvalue is an expression (with an object type other than void) that potentially designates an object.
i itself is an lvalue, but pre-incrementing it like that means it ceases to be so, ++i is an expression not representing any particular object.
In addition to what has already been said, you should not try to deliberately obfuscate your code. You have managed to do this to the point where you don't understand your own code. It would have been much better programming practice to write:
int i = 8;
int j = 0;
int k = 0;
++i;
++j;
++k;
i = 8;
j = 8;
k = 8;
printf("\n %d \t %d \t %d", i, j, k);
Now when we fixed the coding style to use declarations on separate lines, it becomes clear that j and k were not initialized. I fixed that bug above.
"Lvalue required" means you cannot assign a value to something that has no place in memory. Basically you need a variable to be able to assign a value.
in this case your variable having ++operator that acts as both a statement and an assignment
++i = ++j = ++k = 8;
is not valid. The ++ operator acts as both a statement and an assignment, and hence you cannot assign it and provide a value on the right hand side. You can do
i = j = k = 8;
or
i++; j++; k++;
both of which have very different meanings. It looks like you are probably looking to do the first one, since you never assign j or k and incrementing them wouldn't make sense.

Why is the operation on k might be undefined?

Why does the compiler give me the warning that the operation on k may be undefined? What can I do to remove this warning?
int main(void){
int k=0;
int a,b;
do{
k = k++;
printf("The value of k is: %d\n",k);
}while(some condition that does not involve k);
return EXIT_SUCCESS
}
The compiler is letting OP know the sequence k = k++; is not defined by C.
Some compilers may increment k and then assigned the pre-increment value to k - thus overwriting the increment. Another compiler may do the increment, but not yet save the result, assigned the pre-increment value to k, itself and then save the incremented value to k.
All in all, performing code like a = k++ / ++k; or the like, creates problems. The compiler is free to evaluate either the left or right side of the division first, the sequence is not defined, and the you get different answers.
Instead use:
k++;
or
++k;
or
k = k + 1;
refer to this link Undefined Behavior and Sequence Points
k = k++; // k is modified more than once

Is ++ the same as += 1 for pointers?

I'd like to refactor some old C code of mine, and I was curious if I can replace all ptr++ with ptr += 1 where ptris some pointer, without changing any behavior. Here's an example of what I mean, from K&R Section 5.3:
/* strlen: return length of string s*/
int strlen(char *s)
{
int n;
for (n = 0; *s != '\0'; s++)
n++;
return n;
}
When I replace the s++ with s += 1, I get the same results, but I'm wondering if this will be the case for all types. I also did a test for ints:
int size = 10;
int *int_array = (int*)calloc(size, sizeof(int));
for (int i = 0; i < size; i++)
int_array[i] = i;
for (int i = 0; i < size; i++) {
printf("*int_array = %d\n", i, *int_array);
int_array++;
}
If I replace the line int_array++; with int_array += 1;, I get the same result.
After thinking about this some more, I realize there could be a problem if the value is used in an expression. Would it be safer I just moved the increment onto another line like so:
int a = 5;
int b = a++;
would become:
int a = 5;
int b = a;
a += 1;
Conclusion
What I thought could be a problem, incrementing pointers of different types, is not a problem. See #bdonlan's response for the reason why.
This doesn't mean that you can replace all x++ with x += 1 and expect the same behavior. You can, however, replace ++x with (x += 1) safely, since they are equivalent.
a += 1 is equivalent to ++a (C99 §6.5.3.1/2). In a line like int b = a++; this means it is not equivalent to a++; a++ would return the old value of a, while a += 1 returns the new value.
Note that if you don't use the result of a++ (ie, you have a statement containing just a++;), then they are effectively identical.
Also, note that _all pointer arithmetic is done in increments of the pointed-to type's size (§6.5.6/8). This means that:
ptr = ptr + x;
is equivalent to:
ptr = (ptr_type *)( (char *)ptr + x * sizeof(*ptr) );
This is the same whether you use +, ++, +=, or [] (p[x] is exactly equivalent to *(p + x); you can even do things like 4["Hello"] because of this).
++ and -- is defined in terms of arithmetic for built-in types. The behavior will be the same, other than postfix returning the old value.
It's a good question. The answer is yes, you can do that -- no matter how you do it, incrementing a pointer adds sizeof(the type that the pointer points to) to the pointer. As other answers indicate, you do need to be careful that you don't depend on when the increment happens, i.e. a++ and ++a have different effect, but a eventually ends up with the same value.
A question is: why do you want to change all your code from a++ to a+=1? Using the post-increment operator with pointers is something that should be easily understood by any C programmer, so it's hard to understand why you'd make that change.

Resources