difference between: number = number + 10; and number += 10; - c

Is there any difference between these two formats regarding the order of saving the result in the memory?
number = number + 10;
number += 10;
I recall that one format saves the result immediately so the next line of code can use the new value and regarding the other format the new value can't be used by the next line of code. Am I right or wrong about that?

For almost all practical purposes, there is no difference, at least in the simple case you're asking about.
The C standard (the link is to the N1570 draft), section 6.5.15.2, says:
A compound assignment of the form E1 op = E2 is equivalent to the
simple assignment expression E1 = E1 op (E2), except that the lvalue
E1 is evaluated only once, and with respect to an
indeterminately-sequenced function call, the operation of a compound
assignment is a single evaluation. If E1 has an atomic type, compound
assignment is a read-modify-write operation with memory_order_seq_cst
memory order semantics.
(The text formatting of the above paragraph is a bit tricky; += is a single token that can't have a space in the middle of it.)
You can safely ignore most of that. I don't completely understand the last sentence myself.
The relevant difference is that the number is evaluated twice if you write
number = number + 10;
and only once if you write
number += 10;
(It's evaluated once for each time it appears in the expression.)
Now if the expression is just the name of a variable, there is no difference. In both cases, the same value is stored in number, and the result of the entire expression (which is discarded, but it could be used as part of a larger expression) is the new value that was just assigned.
If number is declared volatile, then the number of times it's evaluated can affect your program's behavior. The details depend on where number is stored and the characteristics of your system. Loosely speaking, volatile inhibits optimizations, requiring the compiler to generate code that does exactly what you told it to. If the variable is some kind of special register connected with some physical device, it can make a big difference.
If rather than just number you have a more complicated expression, evaluating it once vs. twice can also make a big difference. For example:
int arr[100] = ...;
arr[rand() % 100] += 10;
arr[rand() % 100] = arr[rand() % 100] + 10;
The first assignment increases the value of some random element of arr. The second grabs the value of some random element of arr, adds 10 to it, and stores the result in some other random element of arr (or maybe the same one), because rand() returns a (probably) different result each time it's called.
But in the simple case you're asking about:
number += 10;
vs.
number = number + 10;
both statements do the same thing, and a compiler will probably generate exactly the same code for both.
The main purpose of the compound assignment operators like += is to let you write shorter and clearer code (the two don't always go together, but in this case they do). Because you're only operating on a single variable, it makes sense to be able to refer to its name only once. And for more complicated expressions, being able to write:
a[b].c[d+42]->e += 10;
rather than
a[b].c[d+42]->e = a[b].c[d-42]->e;
not having to type the name of the target more than once reduces the risk that at typo will introduce a bug. (Did you notice the typo in the second version?)

Related

Does the statement `int val = (++i > ++j) ? ++i : ++j;` invoke undefined behavior?

Given the following program:
#include <stdio.h>
int main(void)
{
int i = 1, j = 2;
int val = (++i > ++j) ? ++i : ++j;
printf("%d\n", val); // prints 4
return 0;
}
The initialization of val seems like it could be hiding some undefined behavior, but I don't see any point at which an object is either modified more than once or modified and used without a sequence point in between. Could someone
either correct or corroborate me on this?
The behavior of this code is well defined.
The first expression in a conditional is guaranteed to be evaluated before either the second expression or the third expression, and only one of the second or third will be evaluated. This is described in section 6.5.15p4 of the C standard:
The first operand is evaluated; there is a sequence point
between its evaluation and the evaluation of the second or third
operand (whichever is evaluated). The second operand is evaluated
only if the first compares unequal to 0; the third operand is
evaluated only if the first compares equal to 0; the result is
the value of the second or third operand (whichever is
evaluated), converted to the type described below.
In the case of your expression:
int val = (++i > ++j) ? ++i : ++j;
++i > ++j is evaluated first. The incremented values of i and j are used in the comparison, so it becomes 2 > 3. The result is false, so then ++j is evaluated and ++i is not. So the (again) incremented value of j (i.e. 4) is then assigned to val.
too late, but maybe useful.
(++i > ++j) ? ++i : ++j;
In the document ISO/IEC 9899:201xAnnex C(informative)Sequence points we find that there is a sequence point
Between the evaluations of the first operand of the conditional ?: operator and whichever of the second and third operands is evaluated
In order to be well defined behavior one must not modify 2 times (via side-effects) the same object between 2 sequence points.
In your expression the only conflict that could appear would be between the first and second ++i or ++j.
At every sequence point the value last stored in the object shall agree with that prescribed by the abstract machine (this is what you would compute on paper, like on a turing machine).
Quote from 5.1.2.3p3 Program execution
The presence of a sequence point between the evaluation of expressions A and B implies that every value computation and side effect associated with A is sequenced before every value computation and side effect associated with B.
When you have side-effects in your code, they are sequenced by different expressions. The rule says that between 2 sequence points you can permute these expressions as you wish.
For example. i = i++. Because none of the operators involved in this expression represent sequence points, you can permute the expressions that are side-effects as you want. The C language allows you to use any of these sequences
i = i; i = i+1; or i = i+1; i=i; or tmp=i; i = i+1 ; i = tmp; or tmp=i; i = tmp; i = i+1; or anything that provides the same result as the abstract semantics of computation asks for interpretation of this computation. The Standard ISO9899 defines the C language as abstract semantics.
There may be no UB in your program, but in the question:
Does the statement int val = (++i > ++j) ? ++i : ++j; invoke undefined behavior?
The answer is yes. Either or both of the increment operations may overflow, since i and j are signed, in which case all bets are off.
Of course this doesn't happen in your full example because you've specified the values as small integers.
I was going to comment on #Doug Currie that signed integer overflow was a tidbit too far fetched, although technically correct as answer. On the contrary!
On a second thought, I think Doug's answer is not only correct, but assuming a not entirely trivial three-liner as in the example (but a program with maybe a loop or such) should be extended to a clear, definite "yes". Here's why:
The compiler sees int i = 1, j = 2;, so it knows that ++i will be equal to j and thus cannot possibly be larger than j or even ++j. Modern optimizers see such trivial things.
Unless of course, one of them overflows. But the optimizer knows that this would be UB, and therefore assumes that, and optimizes according to, it will never happen.
So the ternary operator's condition is always-false (in this easy example certainly, but even if invoked repeatedly in a loop this would be the case!), and i will only ever be incremented once, whereas j will always be incremented twice. Thus not only is j always larger than i, it even gains at every iteration (until overflow happens, but this never happens per our assumption).
Thus, the optimizer is allowed to turn this into ++i; j += 2; unconditionally, which surely isn't what one would expect.
The same applies for e.g. a loop with unknown values of i and j, such as user-supplied input. The optimizer might very well recognize that the sequence of operations only depends on the initial values of i and j. Thus, the sequence of increments followed by a conditional move can be optimized by duplicating the loop, once for each case, and switching between the two with a single if(i>j). And then, while we're at it, it might fold the loop of repeated increment-by-twos into something like (j-i)<<1 which it just adds. Or something.
Under the assumption that overflow never happens -- which is the assumption that the optimizer is allowed to make, and does make -- such a modification which may completely changes the entire sense and mode of operation of the program is perfectly fine.
Try and debug that.

Operands in "int i = 0"

I would like to ask if this short code:
int i = 0;
has 1 operand or 2? The i is an operand, but is 0 too? According to wikipedia, 0 shouldn't (or maybe I misunderstand). If 0 isn't operand, is it a constant or something?
If it is important, the code is in C99.
In int i = 0;, = is not an operator. It's simply a part of the variable initializaton syntax. On the other hand, in int i; i = 0; it would be an operator.
Since = here is not an operator, there are no operands. Instead, 0 is the initializer.
Since you've tagged the question as "C", one way to look at it is by reading the C standard. As pointed out by this answer, initialization (such as int i = 0) is not an expression in itself, and by a strict reading of the standard, the = here is not an operator according to the usage of those terms in the standard.
It is not as clear whether i and 0 are operands, however. On one hand, the C standard does not seem to refer to the parts of the initialization as operands. On the other hand, it doesn't define the term "operand" exhaustively. For example, one could interpret section 6.3 as calling almost any non-operator part of an expression an "operand", and therefore at least the 0 would qualify as one.
(Also note that if the code was int i; i = 0; instead, the latter i and the 0 would definitely both be operands of the assignment operator =. It remains unclear whether the intent of the question was to make a distinction between assignment and initialization.)
Apart from the C standard, you also refer to Wikipedia, in particular:
In computing, an operand is the part of a computer instruction which specifies what data is to be manipulated or operated on, while at the same time representing the data itself.
If we consider the context of a "computer instruction", the C code might naively be translate to assembly code like mov [ebp-4], 0 where the two operands would clearly be the [ebp-4] (a location where the variable called i is stored) and the 0, which would make both i and 0 operands by this definition. Yet, in reality the code is likely to be optimized by the compiler into a different form, such as only storing i in a register, in which case zeroing it might become xor eax, eax where the 0 no longer exists as an explicit operand (but is the result of the operation). Or, the whole 0 might be optimized away and replaced by some different value that inevitably gets assigned. Or, the whole variable might end up being removed, e.g., if it is used as a loop counter and the loop is unrolled.
So, in the end, either it is something of a philosophical question ("does the zero exist as an operand if it gets optimized away"), or just a matter of deciding on the desired usage of the terms (perhaps depending on the context of discussion).
The i is an operand, but is 0 too? According to wikipedia, 0 shouldn't
(or maybe I misunderstand).
The question links to the Wikipedia page describing the term "operand" in a mathematical context. This likely factors in to your confusion about whether the 0 on the right-hand side of the = is an operand, because in a mathematical statement of equality such as appears in the article, it is in no way conventional to consider = an operator. It does not express a computation, so the expressions it relates are not operated upon. I.e. they do not function as operands.
You have placed the question in C context, however, and in C, = can be used as an assignment operator. This is a bona fide operator in that it expresses a (simple) operation that produces a result from two operands, and also has a side effect on the left-hand operand. In an assignment statement such as
i = 0;
, then, both i and 0 are operands.
With respect to ...
If 0 isn't operand, is it a constant or something?
... 0 standing on its own is a constant in C, but that has little to do with whether it serves as an operand in any given context. Being an operand is a way an expression, including simply 0, can be used. More on that in a moment.
Now it's unclear whether it was the intent, but the code actually presented in the question is very importantly different from the assignment statement above. As the other answers also observe,
int i = 0;
is a declaration, not a statement. In that context, the i is the identifier being declared, the 0 is used as its initializer, and just as the = in a mathematical equation is not an operator, the = introducing an initializer in a C declaration is not an operator either. No operation is performed here, in that no value computation is associated with this =, as opposed to when the same symbol is used as an assignment operator. There being no operator and no operation being performed, there also are no operands in this particular line of code.

Compound Assignment Operators in C

What is the output of the following program, and why?
#include<stdio.h>
#include<conio.h>
int main()
{
int a=5;
a +=a += a += 2;
printf("%d",a);
getch();
return 0;
}
The behaviour of your program is undefined as you are reading from and writing to a in an unsequenced step.
What your ancient compiler is doing is correctly following the C grammar rules and is grouping the expression as
a += (a += (a += 2))
But grouping is not the same as sequencing. From this point the behaviour is undefined. Your compiler appears to evaluate the above to
a += (a += 7)
followed by
a += 14
to yield 28.
This is a tough question without an easy, obvious answer.
The expression is probably undefined, in which case it's meaningless to ask "what could be the possible output?", because it could be anything.
If it's undefined, it's because there are multiple writes (stores) to a without any intervening sequence points. The rightmost a += 2 computes 7 and prepares to store it into a. Next we have the middle a +=, which tries to take the 7 and add it to... what? The old or the new value of a? If it's the old we compute 5+7= 12 and if it's the new we compute 7+7=14, and whichever value we compute, we prepare to store it into a, but does it "win" and overwrite the value that the rightmost a += 2 tried to store, or not? And then the arguments (and the multiplicity of different interpretations and possible answers) proliferate for the leftmost a +=.
Not all assignment expressions are undefined, of course. For example, the old standby
a = a + 1
is well-defined. It both fetches from a and assigns to a, but in this case we don't have to ask, "what if it assigns to a before it fetches from it?", because obviously, it has to fetch from a first, in the process of computing the new value to be assigned. But this argument doesn't rescue a += a += 2, I don't think.
There are newer rules about "sequencing" which do away with the old concept of "sequence points", and the new rules might render this expression well-defined, but I'm not sure.
Unless you're interested in frustrating, head-banging puzzles, it's best to steer clear of expressions like this one. You obviously wouldn't have any use for an expression like this in a real program. It's nearly impossible to figure out (a) if the expression is well-defined and (b) if so, what it's supposed to do, so a program containing an expression like this is unmaintainable; you have to be a hard-core language lawyer to properly understand it.
Naturally it's important to understand how simpler, saner expressions like a += 2 or x += y[i++] work. But for something insane like a += a += a += 2, don't fall into the trap of asking "Wouldn't it help me understand C better if I understand what it means?", because the only thing to understand is that it's borderline, if not absolutely, meaningless.
See also SO's canonical entry on undefined expressions, Why are these constructs (using ++) undefined behavior in C? (although none of the answers there cover this particular case).
It depends on the compiler ! But theoretically 28 is the answer !
The assignment will be from right to left so a +=a += a += 2; can be break down as
5+2=7 a+=2
7+7=14 a+=a+=2
14+14=28 a+=a+=a+=2

Why does the following code yield O/P as 3 and not 6? [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 5 years ago.
Why doesn't the value of x increment in the following code?
#include <stdio.h>
int main(){
int x = 3, i = 0;
do {
x = x++;
i++;
} while (i != 3);
printf("%d\n", x);
}
In x = x++, you are saying both to increment x and to assign x a value. The C standard does not define what happens if you do both of these things “at the same time.” For this purpose, “at the same time” means your code has not arranged for one of them to occur before the other.
If you put the increment and the assignment in separate statements, the C standard says that one of them occurs before the other, and then the behavior is fully defined. Technically, there is a sequence point between two such statements. Sequence points are barriers that separate effects. Inside the single statement x = x++, there is no sequence point.
(There is more about sequence points and sequencing in C, but the details are beyond the scope of this question.)
In the simplest C implementation, the compiler might treat x = x++; as if it were x = x; x++; or as if it where int Temporary = x; x++; x = Temporary;. The first would set x to 3 and then to 4. The second would set x to 4 and then to 3. However, the C standard gives implementations a great deal of latitude. In some C implementations, integer types might be made up of parts—a small computer might not be able to handle 32-bit integers all at once, so it might have to do arithmetic in multiple 16-bit steps, or even multiple 8-bit steps. The C standard says, since you have not arranged for the assignment and the increment to occur in a particular order, then, not only is the implementation allowed to do them in either order, it is even allowed to mix the steps. It might do one byte of the assignment, one byte of the increment, the second byte of the assignment, the second byte of the increment, the third byte of the increment, the third byte of the assignment, and so on. In general, you could get a nonsensical answer that is a mishmash of operations on the parts.
So the C standard does not say that, if you do not arrange for the operations to be ordered, then either one happens before the other. It says, if you do not arrange for the operations to be ordered, we do not guarantee what will happen at all. You may get a big mess.

Is there a subset of C can write like this: i=+1?

I remember reading a book talking about standard the C programming language. It said in some kinda C you can write i=+1 which equals i+=1. So i(operator)=(expression) equals i=(operator)(expression). I never see this kind of C, is there someone who can explain this?
Best regards and thanks,
Fan
That was the very very inital syntax for the += operator in C. I think it was deprecated even before the first edition of K&R book.
EDIT: A PDF with the C Reference manaual can be found here:
http://www.math.utah.edu/computing/compilers/c/Ritchie-CReferenceManual.pdf
look at 7.14.1
(Alas, the one posted by AnT is no longer valid)
This is true. That version of C is called CRM C (CRM stands for "C Reference Manual" - a document written by Dennis Ritchie). There are many weird things in that version of C.
You can download the document here http://cm.bell-labs.com/cm/cs/who/dmr/cman.pdf
Kernighan and Ritchie's The C Programming Language, first edition explains this. I found a quote in this post on comp.lang.c. Relevent part of the quote:
Since C is an evolving language, certain obsolete constructions may be
found in older programs. Although most versions of the compiler support
such anachronisms [--as of 1978--], ultimately they will disappear,
leaving only a portability problem behind.
Earlier versions of C used the form =op instead of op= for assignment
operators. This leads to ambiguities, typified by
x=-1
which actually decrements x since the = and the - are adjacent, but
which might easily be intended to assign -1 to x.
Wikipedia also has a similar description. From their entry for C, talking about K&R C and "Old C" differences:
compound assignment operators of the form =op (such as =-) were changed to the form op= to remove the semantic ambiguity created by such constructs as i=-10, which had been interpreted as i =- 10 instead of the possibly intended i = -10.
It would most definitely give issues when you want to assign a negative number to a variable. What decides what you mean then? Spacings? (ew!) Or parenthetis (double ew!). Here are some examples showing the issues
i = -1; //Is this any different from the line below? Since when have spaces in these kind of cases mattered?
i =- 1; //If the suggested syntax existed, what would these two lines mean?
//The only thing left now (if we rule out making spaces matter) is to use parenthetis in my eyes, but...
i =(-1); //This is just ugly
As pointed out in the comments, the * symbol which is used to dereference pointers presents the exact same issue as the minus sign.
This is not C. In standard C that is equivalent to i=1. Might it be that you are looking for i++?
A little bit of whitespace might help clarify this for you.
When you write i=+1, what is actually happening is i = +1. This is because there is no =+ operator in C. The = is treated as its own operator, and the + is a unary operator acting on the constant 1. So the evaluation of this statement starts on the right hand side of the = operator. +1 will evaluate to 1 and the = operator will then assign that value to the variable i.
+= is it's own operator in C, which means "add the value of the expression on the right side of this operator to the variable on the left side, and assign it to that variable, so something like the following:
i = 3;
i += 2;
would evaluate to 5 because the += operator will evaluate the right side of the operator (in this case 2, and will add it to the left side (in this case, i has a value of 3) and will assign it to the variable on the left. In essence, this becomes i = (2 + 3). Therefore, the variable i will have a final value of 5.
If you're just adding the value 1 to an integer variable, you can use the ++ operator instead. Adding this operator after a variable (i.e. i++) will cause the current line of code to execute before incrementing the variable by one. Prefixing the operator in front of the variable will cause the statement to be executed after the variable is incremented.
e.g.:
i = 5;
j = i++;
will result in i = 6 and `j = 5', whereas
i = 5;
j = ++i;
will result in i = 6 and j = 6.
Similarly, the -- operator can be used to decrement (decrease) the variable by one, similar to how ++ will increment (increase) the variable by one. The same rules regarding positioning the operator before or after the variable apply to both operators.
Hope this clears things up a bit.

Resources