C: order of evaluation in a conditional expression [duplicate] - c

This question already has answers here:
Post-increment and Pre-increment concept?
(14 answers)
Closed 5 years ago.
There is the following C code:
#include <stdio.h>
int main ()
{
int a[5] = {0, 1, 2, 3, 4};
int* a_p = a;
float x = 1.5;
while(x > (*a_p++))
{
printf("*a_p = %d\n", *a_p);
}
printf("*a_p = %d", *a_p);
return 0;
}
The question would be which is the result of the final printf statement?
I would judge that the order is:
1) inside while, a_p address is incremented => *a_p is 1 (a[1])
2) 1.5 is compared with 1
3) inside while, a_p address is incremented again => *a_p is 2 (a[2])
4) 1.5 is compared with 2
5) 2 is printed for *a_p
I have tried with 3 compilers and the result is 3.
Why 3 is the correct result? Is first done the comparison and then the pointer is incremented meaning that at step 4 from above, after the comparison is done, *a_p is 3?
Is this always the behavior (is this behavior defined) or is compiler dependent?

Yes that's how post increment works. The while condition is true for 0th and 1th index but when it evaluates to false - the pointer value is already increased as a result it points to index 4 having value 3.
*p++ the value of it will be *p where this p is the old one which is not incremented. Same happens with a_p is here - last time when it is compared the value *a_p++ is 2 but the new value of a_p is pointing to the 4th index. Loop ends and 3 is printed.

Related

What does using array index like this [0,1,2] means? [duplicate]

This question already has answers here:
What does the comma operator , do?
(8 answers)
Closed 6 months ago.
How can an array have an index like [0,1,2]?
And why is [0,1,2]=[2]
Code:
int main(){
int a[]={1,2,3,4,5};
a[0,1,2]=10;
for(int i=0;i<5;i++)
printf("%d ",a[i]);
return 0;
}
Output:
1 2 10 4 5
The comma operator (,) evaluates both expressions and returns the second one (see, e.g., this explanation). I.e., 0,1,2 will evaluate to 2, so a[0,1,2]=10 will result in a[2]=10, which explains the output you get.
a[0,1,2] will be treated as a[2] aka the other indices are ignored.
To test this try: printf("%d ",a[0,1,2]); you will see it prints the
value in index 2 only.
To change the values of multiple indices then you either do it
manually or iterate over them. For example,
a[0] = 10;
a[1] = 10;
a[2]=10;
OR
for(int i = 0; i < 3; i++)
a[i]=10;

++i and i++ in while loop in C

I am using a program to detect the boundary of each data type, which is like this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
/*first while loop using a++ dosesn't give us a right answer*/
int a = 0;
while (a++ > 0);
printf("int max first = %d\n", a-1);
/*second while loop using ++a performs well*/
int b = 0;
while (++b > 0);
printf("int max second = %d\n", b-1);
system("pause");
return 0;
}
After I compile this propram and excute it, it returns:
int max first = 0
int max second = 2147483647
So I try to debug it, and I find out that in the first part, after a++ becomes 1, then it just stop autoincrement and jump the while loop,while in second part it runs well, why is this happening?
The pre-increment operator (e.g. ++b) is done first, and the value of the expression is the incremented value.
That is
int b = 0;
while (++b > 0) ...
will increment b first and then check its value using the larger-than comparison. Since in the very first iteration ++b will make b equal to 1 the condition will be 1 > 0 which is true.
Now the post-increment operator does the increment after the old value is used.
So for example a++ will return the old value of a and then do the increment.
So with
int a = 0;
while (a++ > 0) ...
the very first iteration a++ will return 0 which means you have the condition 0 > 0 which is false and the loop will never even iterate once. But the value of a will still be incremented, so afterwards it will be equal to 1 (when the loop have already ended).
This behavior of the pre- and post-operators should be part of any decent book, tutorial or class.
after a++ becomes 1, then it just stop autoincrement and jump the
while loop
This happens because of the post and pre increment operators and the ; in while loop working together.
a will be incremented by 1 after the condition a++ > 0 is evaluated. Thus, the condition fails. The ; at the end of the while statement results in an empty loop and the next print statement will be executed even if the condition on which the while loop is based returns true.
This is exactly what happens in the second while loop - the pre increment operator will increment b before the condition is checked inside while (++b > 0);. The empty while loop keeps on adding one to the value of b until there is an overflow.
At this point, strictly speaking, you have invoked undefined behaviour because the operation has resulted in overflowing a signed integer.
Let me rewrite the main function you wrote - so that it becomes easier to understand.
int main()
{
/*first while loop*/
int a = 0;
while (a > 0){ a = a + 1; }
printf("int max first = %d\n", a-1);
/*second while loop*/
int b = 0;
b = b + 1;
while (b > 0){ b = b + 1; }
printf("int max second = %d\n", b-1);
system("pause");
return 0;
}
Some observations regarding what happened here:
Because at the beginning of the first while loop - the value of a is 0 - which is not greater than 0; the loop gets skipped at the beginning. As a result, the first printf outputs 0.
At the beginning of the second while loop, before evaluating the loop control condition; the loop control variable b gets incremented by 1, resulting the value of b becoming 1; which is greater than 0. For this reason, the second loop is executed.
While executing the second loop, the value of b keeps incrementing by 1 until the value of b overflows. At this point, the program encounters undefined behaviour - and exits the while loop if the program doesn't crash or keeps executing the loop indefinitely (in which case, at some stage the OS will terminate the program; or ask the user to terminate it - as the program will become non-responsive).
You mentioned that you wanted to measure the limit of int values; I hope this reference and this reference will help you in some way.

Confusion about array initialization in c language [duplicate]

This question already has answers here:
How dangerous is it to access an array out of bounds?
(12 answers)
Closed 3 years ago.
I wrote this code and ran it:
#include <stdio.h>
int i;
int a[] = { 1 };
int main()
{
for (i = 0; i < 10; i++)
printf("%d\n", a[i]);
};
It always gave me the following result
1
0
2
0
0
0
0
0
0
0
I know the length of a[] is 1 and a[1],a[2]... are invalid. But I re-compiled it again and finally I found a[2] always give 2, I am quite confused about the 2, where did it come from and why a[2] is not other numbers such as 0 or some random number?
When you do
int a[] = { 1 };
the number of elements in the array will automatically be adjusted to be equal to the number of elements in the initializer. In this case the initializer contains 1 integer so your code is equivalent to:
int a[1] = { 1 };
You've got an array of length 1 but in the for-loop you are accessing 10 items in it (i.e. accessing a[0], a[1], ... a[9]). This is undefined behavior, and what you are seeing is the data beyond the end of your array.

Retrieval of values in reverse order using pointers [duplicate]

This question already has answers here:
Are negative array indexes allowed in C?
(9 answers)
Closed 5 years ago.
I understand working of *(p+i), but, what actually is happening at memory level when retrieving values with *(p-i) or p[-i] through printf() function ?
#include <stdio.h>
int main() {
int i, arr[5] = {1, 2, 3, 4, 5}, *p;
p = &arr[4];
for (i = 0; i < 5; i++)
printf("%d\t%d\t", *(p - i), p[-i]);
// why does this prints in reverse order?
return 0;
}
It's simple, *(p - i) and p[-i] are exactly the same with different syntax. It's interesting that you can also write, -i[p] with exactly the same meaning *(p - i).
It prints in the reverse order because you start at arr[4] and then subtract i from the pointer, which subtracts 0, 1, 2 one by one until it reaches 4, so it prints p[4], p[3], p[2], p[1], p[0] which is the array arr from the last element to the first.
You have assigned last element address in the pointer and subtracting address one by one and hence it prints in reverse order

Value after the while loop with post-increment

Please explain me why the last printf gives value 11?
I really don't understand why it happened.
When a = 10 the condition is not fulfilled so why this value has changed to 11?
Incrementation goes as soon as the condition is checked?
Code:
int main(void) {
int a = 0;
while(a++ < 10){
printf("%d ", a);
}
printf("\n%d ", a);
return 0;
}
Output:
1 2 3 4 5 6 7 8 9 10
11
Let's look at a++ < 10 when a is equal to 10.
The first thing that will happen is 10 < 10 will be evaluated (to false), and then a will be incremented to 11. Then your printf statement outside the while loop executes.
When the ++ comes on the right hand side of the variable, it's the last thing evaluated on the line.
Try changing a++ < 10 to ++a < 10, rerunning your code, and comparing the results.
The post increment operator increments the value of the variable before it after the execution of the statement.
Let's take an example,
int k = 5 ;
printf("%d\n", k++ );
printf("%d", k );
will output
5
6
because in the first printf(), the output is shown and only after that, the value is incremented.
So, lets look at your code
while(a++ < 10)
it checks a < 10 and then after that, it increments a.
Lets move to a few iterations in your loop.
When a is 9, the while loop checks 9 < 10 and then increments a to 10, so you will get output for that iteration as 10, and similarly, for the next iteration, it will check 10 < 10 but the while loop does not execute, but the value of a is incremented to 11 and thus, in your next printf() , you get output as 11.
Let's look at a simpler piece of code to show what a++ does.
int a = 0;
int b = a++;
printf("%d %d\n", a, b);
I think that you'd expect this to output 1 1. In reality, it will output 1 0!
This is because of what a++ does. It increments the value of a, but the value of the expression a++ is the initial pre-incremented value of a.
If we wanted to write that initial code at the top of my answer as multiple statements, it would actually be translated to:
int a = 0;
int b = a;
a = a + 1;
printf("%d %d\n", a, b);
The other increment that we have access to is pre-increment. The difference there is that the value of the expression ++a is the value of a after it was incremented.
Because it's post-increment. The compiler will first evaluate a<10 and THEN increment a by 1.

Resources