Is it possible to use for loop with misleading syntax? - c

Syntax of for loop:
for(initialization;condition;increment/decrement){
statements;
}
Why is the below code running infinite times and then why there is no syntax error?
int x=10;
for(x++;x++;x++){
printf("\n %d",x);
}

The 3 clauses of the for loop are optional and the only requirement is that they should be valid expressions - the first one could optionally contain a variable declaration. The syntax is valid.
In the 2nd clause the result of the expression is used as a check against zero. You start at 10, so the first check reads the value 10, and so on. It is never zero so the loop won't terminate.
Other than that, there is a sequence point after each for clause, so the code is also valid as far as sequencing goes. This code will of keep counting up until it hits integer overflow, which is undefined behavior.

Why is the below code running infinite times...?
Because the used condition doesn't stop it from executing since it usually never will evaluate to 0.
x is incremented twice at each iteration until it reaches the value defined in the macro INT_MAX (limits.h). After that point, incrementing x invokes undefined behavior.
...and then why there is no syntax error?
x++ is a valid condition and the compiler doesn't check whether the expression you set as condition makes sense or not. It only checks for syntax errors. So the program can be compiled and when running, the loop is infinitely.
So to answer:
Is it possible to use for loop with misleading syntax?
The answer is: Yes. But in this case it will invoked undefined behavior as said above at some point.

The "misleading syntax" you use might be weird and bad, but it's still valid. That's why you don't get an error.
The three clauses in the loop are general expressions, with an exception for the first (the "initialization" expression) which is allowed to be a variable definition.
The reason you get an "infinite" loop is because x++ is never zero (which is the value representing "false"). It will however lead to undefined behavior as it will lead to an arithmetic overflow when you increment beyond the limit of int.
It might be easier to understand what's going on if you translate the for loop into the corresponding while loop (all for loops can be translated as while loops).
The for loop
for (initialization; condition; increment/decrement)
{
statements;
}
can be translated to the while loop
initialization;
while (condition)
{
statements;
increment/decrement;
}
If we now do the same translation for the problematic code:
int x = 10;
for (x++; x++; x++)
{
printf("\n %d",x);
}
it becomes
int x = 10;
x++; // initialization
while (x++) // condition
{
printf("\n %d",x); // statements
x++; // increment/decrement
}
This might make it clearer what's going on and why you get an "infinite" loop.

The for loop is defined in the C Standard in two ways
for ( expressionopt ; expressionopt ; expressionopt ) statement
for ( declaration expressionopt ; expressionopt ) statement
So this for loop
for ( x++; x++; x++ ){
has a correct form that corresponds to the first definition of the for loop.
The loop will be executed until the value x after the third expression x++ will be equal to 0.
If instead of the type int you will use the type unsigned int you will get a correct finite loop because there will not be an overflow that results in undefined behavior for signed int types.
unsigned int x=10;
for(x++;x++;x++){
printf("\n %d",x);
}
To make the loop more clear let's use the initial value of the variable x in your example will be equal to -3.
int x = -3;
for ( x++; x++; x++ ){
printf("\n %d",x);
}
So after the first expression x++ x will be equal to -2, SO as -2 is not equal to 0 the body of the loop will get the control and the printf statement will output -1 because x was incremented also in the condition.
Then the third expression x++ will evaluated. And x will be equal to 0.
So now the condition x++ will be evaluated to logical false because it is the value of x before increment.
From the C Standard (6.5.2.4 Postfix increment and decrement operators)
2 The result of the postfix ++ operator is the value of the
operand. As a side effect, the value of the operand object is
incremented (that is, the value 1 of the appropriate type is added to
it).

Related

foo(x++, y) :: Does the x always incremented after to be send as argument?

Is the increment in case of an expression involving x++ always made after the variable to be copy to a function ?
The call :
foo(x++, y);
The function :
int foo(int x, int y)
{
return x*y;
}
Is that a undefined behavior for all compilers?
Let's see the official descriptions here to get a deeper understanding.
For the postfix operator, quoting C11, chapter §6.5.2.3
The result of the postfix ++ operator is the value of the operand. As a side effect, the
value of the operand object is incremented (that is, the value 1 of the appropriate type is
added to it). [...] The value computation of the result is sequenced before the side effect of
updating the stored value of the operand.
and, regarding the function call, chapter §6.5.2.3
There is a sequence point after the evaluations of the function designator and the actual
arguments but before the actual call. Every evaluation in the calling function (including
other function calls) that is not otherwise specifically sequenced before or after the
execution of the body of the called function is indeterminately sequenced with respect to
the execution of the called function.
So, as per above description, there's nothing problematic in your code as shown above.
The old value of x is passed and then, the value is increased.
However, please note the last part of the second quote, you need to maintain the sanity of the code. For example, you need to make sure, there's no change in value without having a sequence point in between. Something like
foo(x++, x++, y);
will be a problem as, you're trying to changing the same variable (x) more than once.
Consider the following program
#include <stdio.h>
int x;
void foo(int x1 )
{
extern int x;
printf( "x1 = %d\n", x1 );
printf( "x = %d\n", x );
}
int main(void)
{
foo( x++ );
return 0;
}
Its output is
x1 = 0
x = 1
Thus as it is seen the value of the expression x++ is the value of the operand before incrementing
x1 = 0
However the side effect was applied before the function gets the control
x = 1
The program is well-formed and there is no undefined behavior.
Whenever post increment is used, the original value of the variable will be sent to the function. And after that, the value of x will be incremented.

what is the difference between i-- and i-1 in C?

I have been trying to run a code for fibonacci series through recursion and used to pass fib(x, y, i--) which resulted in an infinite recursion while the same code worked well by using fib(x, y, i-1).
Is there any significant reason for this?
i-- passes i to the function then decrements i value in the caller scope.
i-1 passes i-1 to the function and does not change i value in the caller scope.
So yes they're totally different. If fib calls itself, the same number is passed over and over again, resulting in infinite recursion
First of all consider that using i-1 your result will be the value of i minus 1, but the variable i will retain its initial value (there is no assignment). Conversely the use of increment or decrement operators modify the variable (in this case there is assignment. I.e. i++ is equivalent to i=i+1).
Said that, the operators --, decrement, and ++, increment, come in two flavours: prefix (i.e. ++i) and postfix (i.e. i++), the operation of increment or decrement is actuated respectively before or after the use of the expression value depending on where you put it.
While the expression i-1 always execute the operation before to use the result (it behaves as a prefixed decrement operator), using increment or decrement operators as prefix the action, increment or decrement, is performed first then the result is used. On the other hand if the operator follow the expression, postfix, the value will be used, or passed, before the operator is applied.
In your case you are using postdecrement in something like:
void fib(int x, int y, int i)
{
...
if (i = 0)
return;
fib(x, y, i--);
...
}
int main(void)
{
...
fib(10, 20, 30);
...
}
Each time you call fib you pass the initial value of i, then locally decrement its value. It will never become 0 in recursed calls, and your loop will never end.
If you use the predecrement, prefixing the operator to the expression (in this case the variable i), the behavior changes, the decrement is executed before to pass the value, and your program will work (the behavior is the same of i-1):
void fib(int x, int y, int i)
{
...
if (i = 0)
return;
fib(x, y, --i); //Note the prefix
...
}

Puzzled about for loops in C

Just to be clear, I understand how for loops work. However, the different syntax causes me problems... Let me give you an example:
I was looking up a recursive sorting algorithm (insertion sort). The code went like this:
void insertion_recursive(int array[],int size){
int i;
if (size<=1) return;
insertion_recursive(array,size-1);
for(i=size-1;i;i--)
if(array[i]<array[i-1])
swap(&array[i],&array[i-1]);
else
break;
}
I understand how the code works, but the condition for the loop is confusing me:
for(i=size-1 ; i ; i--)
What does it mean? Just leaving 'i' without specifying a condition?
An expression represents a single data item--usually a number. The expression may consist of a single entity, such as a constant or variable, or it may consist of some combination of such entities, interconnected by one or more operators. Expressions can also represent logical conditions which are either true or false. However, in C, the conditions true and false are represented by the non-zero integer values and zero integer value, respectively. Several simple expressions are given below:
a + b
x = y
t = u + v
x <= y
++j
In your example, i is an expression whose value is expression's l-value which is in this case, it is the value of variable i.
The expression will evaluate to true for non-zero i values and false if value of i is zero.
So, for(i=(size-1); i ; i--) is equivalent to for(i=(size-1); i != 0; i--).
In C when trying to evaluate a condition, everything that is 0 is false, and everything else is true.
Even pointers are treated the same way. The constant NULL is actually defined as 0. In C++11 we finally have the null_ptr for type safety.
In C there is no bool type, and in C++ if you cast true to integer you get 1, and false casts to 0.
i by itself is converted to a boolean, similar to if (i) {...} or if (! i) {...}; integers are considered true when nonzero and false when zero.
So, for(i=size-1 ; i ; i--) is equivalent to for(i=size-1 ; i != 0; i--).

How to use post/pre increment operators in addition problems?

main(){
int x = 256, y = 4;
printf("%d\n\n", x++ + ++y); //output = 261
printf("%d\n\n", x); // output = 257
printf("%d", y); // output = 5
}
Is the final answer 261, because 256 -> 257 (post operator) and 5 -> 5 (pre operator) cause 256 + 5 = 261?
Given:
int x = 256, y = 4;
printf("%d\n\n", x++ + ++y);
In short: The x++ returns the value 256 and then increments x to 257. The ++y increments y to 5 and returns the value 5. The addition, therefore, adds 256 and 5 yielding 261.
Long windedly: The x++ evaluates to the current value of x which is 256 and schedules an increment of x to 257. Similarly ++y schedules the increment of y to 5 and evaluates to the incremented value 5. The addition, therefore, adds 256 and 5 yielding 261. The order in which the terms involving x and y are evaluated is not defined, but both have to be evaluated before the addition (though the increments may not be complete when the addition is evaluated). Because there is a 'sequence point' when the arguments (and the expression denoting the function) have been evaluated but before the function is called, the increments must be complete when printf() is called.
The next two statements print x and y as 257 and 5.
Note that those two printf() operations could be combined into one. Neither could be combined with the first without invoking undefined behaviour. (See Multiple increments and undefined behaviour for more information on this topic.)
So, allowing for the fact that I would not express it quite the way you wrote it, you seem to have the correct explanation.
Also, Standard C has required a return type on all functions for over 15 years now (since C99 was standardized). You should write:
int main(void)
for a main() function that takes no arguments. (See What should main() return in C and C++? for the full details.)
Note that this question only invokes fully defined behaviour (at least, in the printf() statements). It is not asking about multiple increments on a single variable between sequence points.
It will show UNSPECIFIED behavior
In your case, we can't tell whether x++ will be evaluated first or ++y will be evaluated first. It is compiler dependent.
So don't use expressions involving a combination of post-increment or pre-increment operators in C or C++.
For more information refer to the link:
https://www.quora.com/What-does-an-expression-involving-multiple-post-pre-decrement-increment-operators-evaluate-to-in-C-and-C++#

Garbage value with post increment

Question 1
int x;
if (x++)
{
printf ("\nASCII value of X is smaller than that of x");
}
Is x assigned here with a garbage value ??
Question 2:
main ()
{
int i;
for (i = 0; i++ < 10;)
{
printf ("%d\n", i);
}
}
Can anyone explain how i++ < 10 works?I mean it should end at 9 why 10
The value of x is indeterminate, and is possibly a trap representation, in which case the behavior of x++ is undefined.
The expression i++ evaluates to the current value of i; as a side effect, the value in i is incremented. So if i == 1, the expression i++ will evaluate to 1, and as a side effect i will be set to 2.
Chapter and verse:
6.5.2.4 Postfix increment and decrement operators
...
2 The result of the postfix ++ operator is the value of the operand. After the result is
obtained, the value of the operand is incremented. (That is, the value 1 of the appropriate
type is added to it.) See the discussions of additive operators and compound assignment
for information on constraints, types, and conversions and the effects of operations on
pointers. The side effect of updating the stored value of the operand shall occur between
the previous and the next sequence point.
Emphasis mine.
In the first question, you declare x
int x;
but you do not assign it, this reserves some memory to hold the value of x, but doesn't initialize it to a known value. That's a really bad thing. Then you read it, increment it, and possibly do something.
if ( x++ ) {
printf ( "\nascii value of X is smaller than that of x" ) ;
}
Since you don't know what it's value was before you read it, it is impossible to make an educated guess as to whether your if statement will print anything.
In your second question (please one question per question), you read the value of i, then increment it, and then do the comparison on the read value. Post increment basically means, "increment the value after I read it" and so the new value will be stored, then the comparison made on the old value, and the printf statement below will print the "current, new" value.
Question 1: Yes
Question 2: Yes. i is incremented by one then compared if it's lesser than 10.

Resources