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.
Related
I am a beginner in C and I came across a code which went like this:
#include<stdio.h>
int main()
{
int k=35;
printf("%d %d %d",k==35,k=50,k>40);
return 0;
}
I tried to find the output without writing the code in my computer and 'actually' running it first. So here's how I figured out what the output might be:
In the precedence table, among assignment (==), equality (=) and greater than (>) operators, the greater than operator will be implemented first. So, initially, k=35 and thus k>40 is false (the integer thus will be 0). Next up is the equality operator (==). Now, k==35 is true initially. So this will return an integer 1. Finally, the assignment operator (=) will do its job, set the value of k to 50(and ultimately, returning 50) and the program will exit. Thus, based on this logic, I 'guessed' that final output will be like:
1 50 0
Now I ran the code in my IDE (I'm coming to my IDE a bit later) and the result it gave was:
0 50 0
So, my confusion is, in which order are the operators being implemented?
Any help or hints are very much welcome.
NOTE: I noticed a bit closer and found that the only way possible is: First the > operator does its job, then the = operator and finally, the == operator.
I changed my printf line a bit and wrote:
printf("%d %d %d",k==35,k>40,k=50);
Here, I found that the output was:
0 1 50
which, again was not according to what I 'guessed' initially with my logic.
I tried all the possible ordering of the syntax inside the printf() function. After looking at all those outputs, I doubt: Is the program being implemented in a right-to-left order here irrespective of the ordering in the precedence table?
NOTE: Regarding my IDE, I use Dev C++ 5.11. I use it as our instructor has advised us to use it for our course. As this IDE is not so much well-received among many others, I tried an online compiler, but the results are the same.
The behavior is undefined - the result is not guaranteed to be predictable or repeatable.
First, precedence only controls which operators are grouped with which operands - it does not control the order in which expressions are evaluated.
Second, the order in which function arguments are evaluated is unspecified - they can be evaluated right-to-left, left-to-right, or any other order1.
Finally, you are updating k (k = 50) and attempting to use it in a value computation (k == 35, k > 40) without an intervening sequence point, which is explicitly called out by the language definition as undefined behavior.
So the result can literally be anything, even what you expect it to be. You can’t rely on it to be consistent or predictable.
This is not the same as the order in which they are passed to the function.
printf("%d %d %d",k==35,k=50,k>40);
This is undefined behavior.
The order of evaluation of the arguments is simply unspecified.
See here and here for further explanation.
Order of evaluation of the operands of any C operator, including the order of evaluation of function arguments in a function-call expression, and the order of evaluation of the subexpressions within any expression is unspecified[...]. The compiler will evaluate them in any order, and may choose another order when the same expression is evaluated again.
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.
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
This was my Interview question in HP. I answered a++ takes less instruction compared to a = a +1;
I want to know which is useful in efficient programming, and how both are different from each other..?
Hoping for quick and positive response..
In C, there would be no difference, if the compiler is smart.
In C++, it depends on what type a is, and whether the ++ operator is overloaded. To complicate matters even more, the = operator can be overloaded too, and a = a + 1 might not be the same as a++. For even more complication, the + operator can also be overloaded, so an innocent looking piece of code such as a = a + 1 might have drastic implications.
So, without some context, you simply cannot know.
First of all, in C++ this will depend on type of a. Clearly a can be of class type and have those operators overloaded and without knowing the details it's impossible to decide which is more efficient.
That said, both in C and C++ whatever looks cleaner is preferable. First write clear code, then profile it and see if it's intolerably slow.
I think I would answer in an implementation independent way. The a++ is easier to read to me because it's just showing me what it does. Whereas for a = a + 1 I first have to scan all the addition. I prefer to go for the choice that's more foolproof.
The former, a++, evaluates to the prior value, so you can use it to express things in sometimes surprisingly simpler manners. For instance
// copy, until '\0' is hit.
while(*dest++ = *source++) ;
Apart from these considerations, I don't think any of them is more efficient, assuming you have to do with basic integer types.
I am not an expert in microprocessor design, but I guess many processors have a INC or DEC instruction. If the data type is int then increment can be done in one instruction. But a = a + 1 requires more, first add and then assignment. So a++ should be faster, obviously assuming that a is not a complex data type.
However a smart compile should do this kind of optimization.
With an optimizing compiler they are identical. The interview question is moot.
As far as I know, there's no difference between a++ and a = a + 1.
HOWEVER, there is a difference between ++a and a = a + 1
Let's take the first case, a = a + 1.
a = a + 1 will have to take the value of a, add one to it, and then store the result back to a.
++a will be a single assembly instruction.
You can notice the difference with these two examples:
Example 1
int a = 1;
int x = a++; //x will be 1
Example 2
int a = 1;
int x = ++a; //x will be 2
BE AWARE! Most compilers optimize this today. If you have a++ somewhere in your code it will MOST likely be optimized to a single assembly instruction.
Even more efficient in many cases in ++a. When a is an int or a pointer though it is not going to make any difference.
The rationale of why these increments are more efficient though than a=a+1 is because the instruction of increment is one instruction whereas the instructions involved in adding 1 to a then assigning it back is something like:
get the address of a
push its contents onto the stack
push 1 to the stack
add them
get the address of a (possibly already stored)
write (pop) from the stack into this address
Really it all boils down to what your compiler does optimize.
Lets take the optimal case of a is an int. Then normally your compiler will make a++ and a=a+1 be exactly the same.
Now what can be pointed out, is that a = a + 1; is purely incrementing the value of the fixed amount 1,
whereas a++ is incrementing the value of 1 of the type of the variable. So if it is an int, float etc you'll get 1->2, 3.4->4.4 in both cases.
But if a is a pointer to a array/list etc, you'll be able to change pointer to the next element in the list/array when using a++, while a = a+1 might do something else or not work at all.
Long answer short, I'd say a++ is better:
your code is clearer and shorter
your can manipulate a wider range of varaibles types
and should be more efficient since (I think but I'm not sure) ++ is a basic operator on the same level as << etc.: it modifies directly the variable, while a = a + 1, if not optimized by your compiler, will require more operations by adding a with another number.
++a;
a+=1;
a=a+1;
Which notation should we use? Why?
We prefer the first version, ++a, because it more directly expresses the idea of incrementing. It says what we want to do (increment a) rather than how to do it.

(add 1 to a and then write the result to a).
In general, a way of saying something in a program is better than another if it more directly expresses an idea.
The result is more concise and easier for a reader to understand. If we wrote a=a+1, a reader could easily wonder whether we really meant to increment by 1.
Maybe we just mistyped a=b+1, a=a+2, or even a=a–1.
With ++a there are far fewer opportunities for such doubts.
Note: This is a logical argument about readability and correctness, not an argument about efficiency. Contrary to popular belief.
Modern compilers tend to generate exactly the same code from a=a+1 as for ++a when a is one of the built-in types.
from http://www.parashift.com/c++-faq-lite/operator-overloading.html#faq-13.15 :
++i is sometimes faster than, and is never slower than, i++.
a++ is better than a+1 because in the case of floating point numbers a++ increments more efficiently than a=a+1. I.e. a++ increments exactly 1 and no rounding takes place.
after reading about sequence points, I learned that i = ++i is undefined.
So how about this code:
int i;
int *p = &i;
int *q = &i;
*p = ++(*q); // that should also be undefined right?
Let's say if initialization of p and q depends on some (complicated) condition.
And they may be pointing to same object like in above case.
What will happen? If it is undefined, what tools can we use to detect?
Edit: If two pointers are not supposed to point to same object, can we use C99 restrict?
Is it what 'strict' mean?
Yes, this is undefined behavior -- you have two modifications of an object without a sequence point between them. Unfortunately, checking for this automatically is very hard -- the best I can think of is adding assert(p != q) right before this, which will at least give a clean runtime fault rather than something worse. Checking this at compile time is undecidable in the general case.
The best tool not to detect, but to avoid this in the first place is to use good programming practice. Avoid side-effects and do no more than one write per assignment. There is nothing wrong with
*q += 1;
*p = *q;
The expression is the same as i=++i. The only tool that can detect it is your head. In C with power comes responsibility.
Chapter 5 Expressions
Point 4:
Except where noted, the order of evaluation of operands of individual operators and subexpressions of individual expressions, and the order in which side effects take place, is unspecified. Between the previous and next sequence point a scalar object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored. The requirements of this paragraph shall be met for each allowable ordering of the subexpressions of a full expression; otherwise the behavior is undefined.
[ Example:
i = v[i ++]; / / the behavior is undefined
i = 7 , i++ , i ++; / / i becomes 9
i = ++ i + 1; / / the behavior is undefined
i = i + 1; / / the value of i is incremented
—end example ]
As a result this is undefined behavior:
int i;
int *p = &i;
int *q = &i;
*p = ++(*q); // Bad Line
In 'Bad Line' the scalar object 'i' is update more than once during the evaluation of the expression. Just because the object 'i' is accessed indirectly does not change the rule.
That's a good question. The one thing you have highlighted is 'sequence points', to quote from this site
why you cannot rely on expressions such as:
a[i] = i++;
because there is no sequence point specified for the assignment, increment or index operators, you don't know when the effect of the increment on i occurs.
And further more, that expression above is similarly the same, so the behaviour is undefined, as for tools to track that down, is zero, sure there's splint to name one as an example, but it's a C standard, so maybe there's a hidden option in a tool that I have not yet heard of, maybe Gimpel's PC Lint or Riverblade's Visual lint might help you although I'll admit it does not mention anything about tracking down undefined behaviour in this regard.
Incidentally, GCC's compiler version 4.3.3 has this option -Wsequence-point as part of flagging up warnings..this is on my Slackware 13.0 box...
It just shows, that code may look ok to the naked eye and will compile just fine, but can cause headaches later on, the best way to do it is to have code review that can spot out things a compiler may not pick up on, that is the best weapon of choice!