Why doesn't this function get stuck in an infinite loop? [duplicate] - c

This question already has answers here:
Is short-circuiting logical operators mandated? And evaluation order?
(7 answers)
Closed 3 years ago.
This function is from my professor's notes:
int ints_is_sorted_r(int* a, int n){
return n <= 1 || (a[0] <= a[1] && ints_is_sorted_r(a+1, n-1));
}
This is my version with many printfs to see what it does
int ints_is_sorted_r(int* a, int n){
printf("n <= 1 = %d\n",(n <=1));
printf("a[0] <= a[1] = %d <= %d\n",a[0],a[1]);
ints_println_special(a,n);
return n <= 1 || (a[0] <= a[1] && ints_is_sorted_r(a+1, n-1));
}
(ints_println_special() is a function from my prof's library that prints the whole array)
My question is, how does the recursion stop? Here's the output from my test:
My guess is that when you have an OR condition and the first one is true it doesn't waste time looking for the right side of the condition because it knows it's going to be true anyway. Am I correct?

My guess is that when you have an OR condition and the first one is
true it doesn't waste time looking for the right side of the condition
because it knows it's going to be true anyway. Am I correct?
Yes, you are correct! It's called "short-circuiting" and there are several good posts here on Stack Overflow that explain and discuss it, like this one.
PS: Note that there could also be (probably will be) such short-circuiting, internally, in the part after the || operator; so, in (a[0] <= a[1] && ints_is_sorted_r(a+1, n-1)), if the first comparison, a[0] <= a[1], is FALSE, then the second won't be evaluated, and the function won't be called recursively in that case.

Related

Does (--n) equal (n - 1)? [duplicate]

This question already has answers here:
What is the difference between ++i and i++?
(20 answers)
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 4 years ago.
I've recently started trying to learn C & was doing an exercise that involved creating a recursive factorial function.
Why does the following print out an answer of 24?
#include <stdio.h>
int factorial(int n);
int main(void)
{
int n = 5;
printf("%d\n", factorial(n));
return 0;
}
int factorial(int n)
{
if (n <= 1)
return 1;
else
return n * factorial(--n);
}
If i change the last line to
return n * factorial(n - 1);
I get the expected 120.
I understand that you can't use n-- b/c it only decreases n after the line is processed but whats wrong with --n & why does it give 24?
whats wrong with --n & why does it give 24?
The problem is that --n modifies n, so your line
return n * factorial(--n);
may evaluate like:
return (n - 1) * factorial(n - 1);
because the factorial(--n) is evaluated before the n that is the first term of the expression. On the other hand, the first term could be evaluated before the second, and you'd get the result you expect. Or, something entirely different could happen, because (as M.M and David C. Rankin point out in comments) what happens when you try to use a variable and modify it in the same expression is undefined:
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined.
So let's address your title question:
Does (--n) equal (n - 1)?
The values of --n and of n - 1 are the same, but the former expression has the side effect that it modifies n. You should really think of --n as being shorthand for the expression (n = n - 1).

explain these how the conditional operator helps in counting the negative and positive numbers in an array? [duplicate]

This question already has answers here:
The ternary (conditional) operator in C
(14 answers)
Closed 5 years ago.
my confusion is that how in the program the number of positive and negative numbers are calculated by writing that piece of code shown.
explain these code please!
int num[5], i, neg = 0, pos = 0;
printf("enter any 5 numbers");
for (i = 0; i <= 4; i++)
scanf("%d", &num[i]);
for (i = 0; i <= 4; i++) {
num[i] < 0 ? neg++ : (pos++);
}
printf("\nnegative elements=%d", neg);
printf("\npositive elements=%d", pos);
getch();
num[i]<0?neg++:(pos++);
Here, If number less then zero then condition become true and count the negative numbers and If number not less then zero then condition become false and count positive numbers.
The line
num[i]<0?neg++:(pos++);
means- compare num[i] to 0, if it is lower, increase the variable neg. Otherwise (num[i] >= 0), increase the variable pos.
hope this helps
Since, most answers have explained the ternary operator, I need not do it again.
The neg++ post-increments the previous value of neg variable. And the same goes for pos++.
Here's a link on post/pre increments.
The ternary operator used as an expression statement evaluates like an if statement:
num[i] < 0 ? neg++ : (pos++);
is equivalent to
if (num[i] < 0)
neg++;
else
pos++;
This kind of coding is not considered good style, and there are other issues in the code fragment posted:
the return value of scanf() should be checked to avoid undefined behavior if the input cannot be converted to an int.
the loop index should be compared to the array size with i < 5 instead of using the <= operator and a close but different constant.
output lines should be terminated with newline, not initiated with one.
getch() is a non standard function. Its purpose is to force a pause before the program exits. Fixing shortcomings of the environment inside the program is a sad workaround. Opening a terminal window to execute programs is a better alternative: it allows the programmer to observe all program output including any extra runtime messages occurring upon program termination.

understanding the behaviour of this C program [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 9 years ago.
i begin Why the output produce 002?
Thanks for the edit and the answers but I'm still confused.
Here is the code:
#include <stdio.h>
int t[3],i;
int main()
{
for(i=0;i<3;i++)
t[i]=i++;
for(i=0;i<3;i++)
printf("%d",t[i]);
}
002
Can anyone help me understand why it is so?
It's because you incremented your i counter twice in your for-loop (once at t[i] = i++, once at the end statement of your for-loop, i++). That way, the for-loop is executed twice (not three times), once for i = 0 and once for i = 2. Hence your output.
To convince yourself, try adding prints as in
for(i=0;i<3;i++) {
printf("%i ", i);
t[i]=i++;
}
and see how many times your for loop gets executed and for which values of i it does.
Download a copy of the C standard (for example, google for N1570, that will give you the latest freely available version). In that document, look for "sequence point" and read what it says.
In short: Your program is rubbish and could do whatever it likes, for the reasons explained in this document. (Basically, the statement t [i] = i++; invokes undefined behaviour. This is a very special case of a general rule set in the C Standard. C++ and Objective-C have the same rule).
You are incrementing i twice in each iteration. In first iteration i = 0, so t[0] = 0 then you are doing i++ twice. In second iteration i=2 so t[2] = 2 and now loop is ending. t[1] is uninitialized.You are getting 002 because:the first 0 from t[0]the second 0 is garbage value or null value from where t[1] is stored in the memory (in your case it is 0 )and the last 2 from t[2]

"--" operator in while ( ) loop

I am reading K&R book, on page 63 there is a line
while (--lim > 0 && (c=getchar()) != EOF && c != '\n')
where lim is int equal to 1000
My question, why is lim is not decreasing after consequential runs of while loop ?
As I see it, --lim is equivalent to "lim = lim - 1"
===================================================================
Thanks for all the answers !
--lim means "take one from the value of lim and use the result".
The alternative lim-- would be "use the value of lim and then take one away".
So if lim starts at 1000 the first time the loop executes it will have the value 999 before it is checked to see if it's greater than 0. If it were lim-- then the value that would be checked would be 1000, but it would still have the value of 999 at the end of the iteration through the loop. This is important at the start and end of the loop.
The MSDN as a page on this Prefix Increment and Decrement Operators
When the operator appears before its operand, the operand is incremented or decremented and its new value is the result of the expression.
Are you sure?
#include <stdio.h>
int main()
{
int lim = 10;
while (--lim > 0 && printf("%d\n",lim));
}
ouput:
9
8
7
6
5
4
3
2
1
Lim is decreasing, you probably made a mistake elsewhere. However, --lim is not quite equal to lim = lim - 1.
There are two operators to perform increment/decrement of a variable: pre-increment(or decrement), and post-increment(or decrement).
++x (pre-inc) and x++ (post-inc) both modify the value of x by +1. So what's the difference?
When you use x++ in an expression, the expression will consider x to have it's current value and after evaluating everything accordingly, increment that value by one. So...
int x = 5;
printf("%d", x++);
... will print out 5. HOWEVER, after the printf() line, the value of x will be 6.
Pre-increment works the other way round: the value of x it's first incremented, and then considered to evaluate the expression surrounding it. So...
int x = 5;
printf("%d", ++x);
... will print out 6 and, of course, the value of x will be 6 after that.
Of course, the same applies to the decrement operators.
Now, the assignment operation (x = x + 1) evaluates to the value assigned, after the assignment happened, so its behavior is actually similar to ++x, not x++.
Try to compile and run this code. It should be somewhat enlightening.
#include <stdio.h>
int main()
{
int lim = 10;
while (--lim > 0 && 1 > 32)
printf("I should never get here\n");
printf("%d\n",lim); // lim is now 9
}
Oh look, lim is now 9 even though I never actually entered the loop because 1 isn't greater than 32.
--lim or lim-- is a short hand of lim = lim - 1, So maybe author want to use this syntax to better clarify!
Excluding David's example (where the initial test of 'c' causes the loop body to never be executed, and thus lim is not decremented), and the possibility that lim is initially less than or equal to 1 (in which case the getchar() would not be executed), the code is equivalent to the following:
c=getchar();
while (lim > 1 && c != EOF && c != '\n')
{
lim = lim - 1;
/* Original body of loop */
c=getchar();
}
Both exceptions are rather unlikely and probably inconsequential, so you could use the above code if it's easier to understand.

Recursion in C with Pre increment [duplicate]

This question already has answers here:
Why are these constructs using pre and post-increment undefined behavior?
(14 answers)
Closed 5 years ago.
int fact_rec(int n)
{
printf("%d\n",n);
if(n==1) return n;
else return fact_rec(--n)*n;
//else return n*fact_rec(--n); gives same result
//correct output comes for n*fact(n-1)
}
In the above recursive implementation of the factorial function,
fact_rec(5) returns 24. Whereas, if I use
n*fact_rec(n-1)
in place of
n*fact_rec(--n)
the output is correct : 120.
Also, it doesn't matter whether I use
n*fact_rec(--n)
or
fact_rec(--n)*n.
Shouldn't it matter if I use
n*fact_rec(--n)
or
fact_rec(--n)*n?
And shouldn't the output have
been 120 in all the cases?
return fact_rec(--n)*n
is dangerous. The order of argument evaluation is undefined in C (except for &&, ||, comma and ternary operators) so value for second occurrence of n could vary.
The rule of thumb: never use variable you are incrementing/decrementing twice in one expression.
Your confusion seems to be about the order - unlike the other answers, I am assuming you already know what --n does...
The compiler knows it needs the value of fact_rec(--n) before it can evaluate fact_rec(--n)*n whichever way round you write it, so the function is evaluated first, and the value of n multipled has always already been decremented.
There is actually no need to modify n at all. return n * fact_rec(n - 1) takes care of it and is the right way to do it.
--n in your function really means:
int fact_rec(int n) {
printf("%d\n",n);
if(n==1) {
return n;
} else {
n = n - 1; /* <---- effect of --n */
return fact_rec(n)*n;
}
}
The problem is here:
else return fact_rec(--n)*n;
you're decrementing n before the multipliation
so if n starts as 5 it runs as
return fact_rec(4)*4;
Edit: Down voted for a correct answer to the question? I don't get it.

Resources