Puzzled about for loops in C - 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--).

Related

Is it possible to use for loop with misleading syntax?

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

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

Can't understand this if statement

I've a C university exam coming up next week and i was looking at old exam papers a one of the questions gives this fragmented bit of code.
int a=2, b=-1, c=0;
if (a-2||b&&c||a){
printf("True\n");
} else {
printf("False\n");
}
We have to determine what the output of this code will be but the if statement makes no sense to me any if statement I've come across has been very specific like saying
if( x == 0)
I don't know what this is looking for my only assumption is that its going to be always true. Am I right or is there more to it then that?
This assignment has two goals:
to show what booleans are in C: Essentially they evaluate to ints with false mapping to 0 and true mapping to 1. In turn, any numeric or pointer value can be used in an integer context, with the respective zero value (0, 0.0, NULL (pointer), 0.0f, 0L etc.) evaluating as false and all others as true.
to show the precedence of operators
&& has a higher precedence than ||, so this statement is equivalent to
a-2 || (b&&c) || a
which will evaluate to true if any of the values is true.
As a==2, a-2 is 0. c is 0, so b && c is 0 as well.
So we have 0 || 0 || a, which is true as a is 2.
Most languages interprets non-zero integers as true and zero as false, so here you would have to calculate each one of the terms. Without any parenthesis, I would suggest that the && statement is taken in account first. So we have:
if (2-2 // gives zero
|| // OR
-1 && 0 // -1 AND 0 gives false
|| // OR
a) // Which is 2, which is true
So you're right, this statement is always true. This exercice was about showing predecence orders, and the fact that everything is numerical, even in boolean logic.
This is really important for you to understand.
If the predecence was the other way around (|| > &&), you must understand that it would have been false instead. I think this example's whole point is here.
(a-2 || b) && (c || a)
false && true
--> false
You need to understand that truth and falsity in C is always numerical.
https://www.le.ac.uk/users/rjm1/cotter/page_37.htm
Namely, anything that evaluates to numerical zero is false, and anything that evaluates to numerical non-zero is true.
In c language integers 0 is treated as false and any non-zero integer value is true but it should be noted that it is language specific and the sme statement will show compilation error in java as java is more strict and integers are not converted to booleans.
Talking about the above assignment problem the expression inside if statement will evaluate to true as
(a-2||b&&c||a) is same as
(2-2||-1&&0||2) which is same as
(0||0||2) which is evaluated as
(false||false||true) and hence the entire expression evaluates to
true.
hope it helps.
int a=2, b=-1, c=0;
int first=a-2; //0 -> false
bool second= b&& c; // nonZero&&zero -> true&&false -> false
int third = 2; // nonZero -> true
// false|| false|| true -> true
if (first || second || third ){
printf("True\n");
} else {
printf("False\n");
}
you need to understand two things before solving this problem that is
operator precedence and
associativity of operators
operator precedence tells c compiler that which operation to perform first.
and if two operators have same precedence than associativity tells evaluate left to right or right to left in you expression
int a=2, b=-1, c=0;
if (a-2||b&&c||a){
you can think it as
if((a-2)||(b&&c)||a){}
means - has top precedence so it will solved first
reduced to if(0||(b&&c)||a){}
then && has higher precedence so
reduced to if(0||false||a)
then the associativity is left to right so
reduced to if(false||a)
that is(false||2)
return true
In almost every programming language as far as I know 0 means false and 1 means true.
So coming up to your question: you have used && and || operators. Both of these are called Logical operators.
Now first block of yours is a-2||b :-
2-2||-1 so 0||-1. Now since the right expression of || is -1 the or operator will return 1 i.e. True because one of the values of 0 and -1 is non-zero 0 i.e. -1.
Therefore the expression resolves to 1&&c||a :-
Now c=0, therefore 1&&0 returns a 0 because && will only return 1 if both the expressions right and left of it are non zero.
So expression becomes 0||2 :-
Now since || (or operator) requires only one of operands either on right or left side to be non zero hence 0||2 returns 1.
Now your if (a-2||b&&c||a) statement resolves to
if (1)
{
printf("True\n"); }
else......
Therefore since 1 means TRUE the if statement will execute and you will get output as True.

return counter==0 produces a boolean or integer?

I'm beginner on C and checking this code
int is_finished()
{
int counter = 0;
sem_wait(&global_mutex);
counter = NotEatenCount;
sem_post(&global_mutex);
return counter==0;
}
the function should return an integer. What does return counter==0 means in here? It looks like:
if(counter==0){
return true;
}
else{
return false;
}
== evaluates to an integer that is either 0 or 1, depending on the comparison outcome. In this case, the function will return 1 (true) if counter is equal to 0; it will return 0 otherwise.
Since you are using the 'equal to' operator and not the 'assignment' operator you will get a boolean function (Difference here: http://en.wikipedia.org/wiki/Operators_in_C_and_C++). So how your return statement is deciding this is:
return (counter == 0);
I believe what you want to return here is
return counter
then outside of your is_finished() function equate if counter == 0 or not and have that represent your bool.
return counter==0
it returns the int value 1 if counter is equal to 0 or the int value 0 otherwise.
In C equality and relational operators always yield an int value of either 0 or 1. Note that this is different in C++ where by default these operators return a value of type bool.
The best solution is to check - print the typeof (:
Anyhow, the answer is both. In C, the true/false keywords are not built-in the language. They are merely a definition, or a part of a library that uses these, for example:
#define TRUE 1
#define FALSE 0
Such definitions are saved as integers if they are numbers, and thus, every boolean is an integer (but the opposite is not true... unless you define it that way). The norm is that 0 is FALSE, and the rest is TRUE.
EDIT: Looking back, I've actually answered a similar question that has to do with objective C. If you're intrested, take a look here.
I prefer to avoid using true and false because they are inherent in the way you use the C language.
Integer values 0 are false. Non-0 values are true. So
if (apples) {...}
will execute when apples != 0.
The C language will give a value of 1 in response to a specific test.
int a = (apples > 0);
That is not so in all languages, some give -1 for true. But there is never any need to compare with 0, true, or false.
if (a) {...}
Only clumsy code will try to use true and false. Otherwise, the logic flow is sweet.
To point out the absurdity of a statement using TRUE
if ((ptr == NULL) == TRUE) {...}
when
if (ptr == NULL) {...}
does the job.
return counter==0 produces an int because the return type is int.
It has a value of 0 or 1.
counter==0 itself produces an int.
The == (equal to) and != (not equal to) operators are analogous to the relational operators except for their lower precedence.) Each of the operators yields 1 if the specified relation is true and 0 if it is false. The result has type int. ... C11 ยง6.5.9 3
The function returns an int regardless even is the 3.14 was attempted to be returned - it will be converted to an int. #wildplasser
int is_finished(){
...
return true;
...
return 3.14
}

Understanding the exit condition of a 'for' loop

I had this question after reading the Stack Overflow quesion Print an int in binary representation using C.
In a user's comment, they posted this for loop, which assigns either a 1 or a 0 to the bit position in order to convert from an int decimal to char * binary.
for(; bits--; u >>= 1)
str[bits] = u & 1 ? '1' : '0';
I understand why there doesn't need to be an initialized value. This is the syntax for a for loop that I've always known:
for ( variable initialization; condition; variable update )
I don't understand how 'bit--' can be an exit condition. Please help me understand how this code works (I tested it, and it is valid).
In C, a value of zero evaluates to "false" in a Boolean context. So when bits-- evaluates to 0, in the context of the loop it evaluates to "false" and terminates the loop.
If you say, for example:
int x = 1;
if (--x)
{
printf("True!\n");
}
else
{
printf("False!\n");
}
It will output "False", because --x evaluates to 0, which is "false" in a Boolean context.
All conditions basically boil down to checking whether something is 0 or not. 0 means false, everything else means true. So that loop will break when bits is 0.
You will sometimes see while or if conditions written
if (variable) // or while(variable)
That is just shorthand for
if (variable != 0) // or while (variable != 0)
So
for (; bits--; u >>= 1)
is short for
for (; bits-- != 0; u >>= 1)
bits-- is an assignment expression of type int (since it will return the value of b, which is int). To match the for loop syntax, it gets converted to a Boolean expression, which means it is true if bits != 0.
In fact, the condition is identical to bits!=0, but by using bits--, it changes the value of bits at the same time, making the code more compact. That's all.
As others said, in C, you can use integers as a condition - 0 or false, and anything else for true. (Actually, you almost always do it - even an expression like a<b is an int.)
So, the loop will end when bits-- will be 0.
When the -- operator comes after the variable, it decreases the variable, and gets the previous value of it. For example, if you have int a=3,b; b=a--;, then b will be 3, and a will be 2.
So, the loop will exit after that bits will been decreased from 0 to -1.
That means that, if in the beginning, bits==8 (for example), the loop will iterate 8 times, when in the first, bits will be 7 (because the condition had checked), and in the last, bits will be 0. It is a nice way to loop through an array (Since in C, an array of bits variables is being indexed from 0 to bits-1).

Resources