What in the world does this statement mean? [duplicate] - c

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
What does this line of code mean?
I was reading an article on Opencv, and came across this:
for( i = 0; i < (faces ? faces->total : 0); i++ )
{
CvRect* r = (CvRect*)cvGetSeqElem(faces, i);
}
What in the world is this line supposed to mean:
i < (faces ? faces->total : 0)

It's the conditional operator.
The (faces ? faces->total : 0) tests faces. If it's true, then faces->total is returned and compared with i. Otherwise, if it evaluates to false, i is compared to 0.

EDIT: Per Femaref's comment, my code below (original response) is not equivalent. faces is likely modified by calling cvGetSeqElem, which in turn means that faces->total is probably modified as well. So, the condition may change in each iteration and, if faces is null (0), the loop exits.
Still, it's confusing (got me!). You could just as easily check for faces being null and exit the loop. The loop counter potentially changes in each iteration, is dependent upon the cvGetSeqElem function mutating it, and just bleh.
It is a shorthand if statement called the conditional operator. It is much the same as:
int count = 0;
if( faces )
count = faces->total;
for( i = 0; i < count; i++ ) {
CvRect* r = (CvRect*)cvGetSeqElem(faces, i);
}
So, if faces is null, count is 0 and the loop body never executes because the first test fails. Of course, you could just check first if that is null and avoid the whole thing together. That code is ugly IMO.
if( faces ) {
// do loop
}
Also, if faces->total is > 1 then you are just wasting cycles as only the last value returned by cvGetSeqElem will persist. Of course, that function could have other side effects that are being relied upon, which would make the code even more convoluted than it already is.

It's iterating up to a value that is a member in a structure.
If the structure pointer is NULL, then it iterates zero times.
It's a safety feature to prevent dereferencing a NULL pointer.

it is equivalent to
int output;
if(faces == 0)
output = 0;
else
output = faces->total;
(Note: this is just an explanation for the part in the for loop, not a replacement)
This is a trick in C. faces is in fact a pointer to a struct (visible by the -> dereferencing). There is no Boolean type in C, 0 means false, every other value is true. In this case, the pointer is implicitly cast to int and than interpreted as Boolean in the conditional operator.
The loop is terminated once the pointer to the struct is NULL. faces is changed in the cvGetSeqElem.

The ternary operator: "if faces is true, then faces->total, otherwise zero".

Related

What is happening here while post/pre decrementing a char variable in C [duplicate]

This question already has answers here:
What is the difference between ++i and i++?
(20 answers)
Closed 4 years ago.
I was solving some multiple choice C codes from a book. Two of the questions involve pre decrementing, post decrementing a char variable initialised at 0. The output for both these is very different. I dont understand whats going on there.
Code 1
char i=0;
do
{
printf("%d ",i);
}while(i--);
return 0;
The output for this snippet is 0.
Code 2
char i=0;
do
{
printf("%d ",i);
}while(--i);
return 0;
The output is for this one is
0,-1,-2,.....-128,127,126,......1 .
Can anyone explain why this is happening?
At both code while loop checking i==0 or not. If i!=0it will keep going on.
At first code value of i initially 0. So after printing 0 it checks i==0 or not. if i==0 it will break the loop or keep going on by decrementing i. So in code 1 post decrementing used. check value first then decrements the value.
At second code value of i initially 0. So after printing 0 it decrements i then it checks if i==0 or not. it is pre decrement. decrement value first then check.
Here, i is char which size is 1 byte and range -128 to 127. So after decrementing value 0 to -1 it keep decrementing until it goes to 0 and exit the loop by printing 0,-1,...,-128,127...1 .
Code 1
char i=0;
do
{
printf("%d ",i); // print o
}while(i--); //check i = 0, means false, loop ends, then increment i
return 0;
Code 2
char i=0;
do
{
printf("%d ",i); //print 0
}while(--i); //decrement i, check i=-1, means true, next cycle, loop until i = 0 which means false
return 0;
Both i-- and --i are expressions. An expression is (part of) a statement that can yield a value. As per definition, the pre-increment version increments first, then yields the value. For the post-increment version it is the other way round.
This is completely independent of whether the expression is used in a while statement or elsewhere. However, when using such expressions, you need to be aware of operator precendence.
Initial value of i is 0.
In Code 1, first while check happens in which the value of i (= 0) is used and then i is decremented because it is postfix decrement. So it exits while after printing 0.
In Code 2, because it is prefix decrement, i is decremented first and its value (= -1) is used when the while check is performed. Here it exits after printing the entire range of values a signed char can hold because it becomes 0 at the end only.

Working of Nested IF-Else Without the Braces

Can someone please explain me the working of Nested If-Else Statements written WITHOUT the Curly Braces.
I want to understand why Below Programme isn't giving me any output.
I've checked for all the 4 possibilities.
(Outer-If, Inner-If)::(True, True),(True, False),(False, True),(False, False).
I'm editing with CodeBlocks,using gcc compiler on Windows.
int main()
{
int n=0,m=0;
if ( n > 0 )
if ( m > 0 )
printf("Inner-If Condition satisfied.");
else
printf("Inner-If condition not satisfied. ");
return 0;
}
Thank You.
They work as-if there was a curly brace around the following statement. In your case then:
if ( n = 0 ){ // ToDo - did you mean `==`, `n = 0` is `0`.
if ( m = 0 ){ // ToDo - ditto.
printf("True");
} else {
printf("False");
}
}
In your case I think the bewilderment stems from your using = rather than ==.
The if-else ambiguity is solved by defining that an ambiguous else belongs to the nearest if.
The parser will see an ambiguity, however, the parser has ben adapted to solve the ambiguity as described above (e.g. yacc).
Note: the reason your program does not give any output is because n=0 (an assignment) results in n being zero and so the test becomes false, so the branch is not taken and the return is executed.
n = 0 is an assignment in C. It assigns n the value 0. Assignments also evaluate to the value that is assigned, so here, to 0, which is in a boolean context false -- so your outer if is always false.
To compare two values, use == instead, which evaluates to 1 (true) on equality, 0 (false) on inequality. *)
Your assumption about if and else was correct, the reason you don't see output is just your wrong attempt at comparing values.
A good compiler will warn you of such typos. E.g. with gcc, enable a reasonable set of warnings with -std=c11 -Wall -Wextra.
*) as a side note, in a boolean context, a zero value is false and any other value is true, so you could also write the code like this (! is logical not, inverting true and false):
if (!n)
if (!m)
// ...
Whether this is good style depends on who you ask. I personally like to write it this way if 0 semantically represents the lack of a value, or if the variable is already meant as a boolean value. Then "if not n" sounds kind of natural.
Use == inside if Statement. such as below mentioned code will work.
if ( n == 0 )
if ( m == 0 )
printf("True");
else printf("False");

Unintentional infinite 'for' loop

I just started programming in C, and while practicing with for loops, I came up with the following piece of code:
#include <stdio.h>
int main()
{
int x;
for (x=0;x=10;x=x+1)
printf("%d\n",x);
return 0;
}
When I run the code, I fall into an infinite loop. In my C manual it says that the condition x =10 is always true, but I can't get my head around it. If I give the variable x a value of 0 at the beginning, should the for loop not even start, or when the value of x reaches 10, shouldn't the loop stop?
Thanks in advance!
The condition part of your for loop is wrong. What you are doing is :
for (x = 0; x = 10; x = x +1) {
// Operations
}
The condition you have got here is x = 10 which is an affectation. So x = 10 will return 10, which also means true. Your for loop is equivalent to :
for (x = 0; true; x = x + 1) {
// Operations
}
This is why you have got an infinite loop, you should replace the affectation operator = by the comparason one with two equals sign ==. This means the for will loop while x is equals to 10.
EDIT : As Virgile mentioned in comments, for the second for loop, x will go from 0 to INT_MAX, then the behavior is undefined. So, your code is more likely to look like :
for (x = 0; true; x = 10) {
// Operations
}
When entering a for loop, the initialization part is performed first. So after the loop initialization x is 0.
Before entering the body of the loop, even the first time, the condition is checked. The "condition" in this case does not compare x to 10 but sets it to 10 since you are using = instead of ==.
Since an assignment as an expression has the value of the variable after assignment, the conditional expression has a value of 10 since that is what was assigned to x. Because this value is non-zero, it evaluates to true, and always will.
The problem here is, Take a close look on the condition part(2), in this what x=10, means is it is just assigning the value 10 to x, and it returns "True" always, so no problem what you have incrementing, it comes to 10 always, Thus infinite loop.
What you are trying to do is, you are implicitly converting int to bool in this line:
for (x=0;x=10;x=x+1)
^^^^
here, x=10; results true
So, it prints 10 everytime as you are using the = assignment operator.
for(int x=0;true;x=x+1)
What you could do to maintain the loop?
Use relational operators:
for (x=0;x!=10;x=x+1)
for (x=0;x==10;x=x+1)
for (x=0;x<10;x=x+1)

Preincrement in character pointers [duplicate]

This question already has answers here:
What is the difference between ++i and i++?
(20 answers)
Closed 7 years ago.
I was toying with the concept of array pointers. I wrote this simple program:
#include <stdio.h>
int main (int argc, char **argv){
char s[] = "Hello world!\n";
char *i;
for (i = s; *i; ++i){
printf(i);
}
return 0;
}
which gives the very amusing output:
Hello world!
ello world!
llo world!
lo world!
o world!
world!
world!
orld!
rld!
ld!
d!
!
When I wrote this, however, I was under the impression that the output would start from the second row. Reason being, in the for loop, I use a pre-increment notation. i is set to the beginning of s, the Boolean condition is checked and it holds true, then i gets incremented and the block executes.
That was my impression, but obviously it is erroneous as the block executes before i gets incremented. I rewrote the program using a post-increment notation and got exactly the same result which confirms my hypothesis. If that is the case, then how are they treated differently in this program?
for (initialization; condition; increase) statement;
This for works in the following way:
initialization is executed. Generally, this declares a counter variable, and sets it to some initial value. This is executed a single time, at the beginning of the loop.
condition is checked. If it is true, the loop continues; otherwise, the loop ends, and statement is skipped, going directly to step 5.
statement is executed. As usual, it can be either a single statement or a block enclosed in curly braces { }.
increase is executed, and the loop gets back to step 2.
the loop ends: execution continues by the next statement after it.
There is no difference between postincrement and preincrement because increase is executed separately anyway.
The increment expression of the for loop is executed after the body. For your case
for (i = s; *i; ++i){
printf(i);
}
is similar to
i = s; // loop init
while (*i) // loop condition
{
printf(i);
++i; // loop increment
}
i is set to the beginning of s, the Boolean condition is checked and it holds true, then i gets incremented and the block executes.
Not quite. The actual syntax is
i is set to the beginning of s
the Boolean condition is checked
2.1. if it holds true the block executes,
2.2. come out of loop otherwise.
then i gets incremented and continue to step 2.
Note: In this particular scenario, pre and post increment to i are not going to make any difference.
the equivalent of
for( a ; b ; c )
{
statements
}
is
a ;
while( b )
{
statement
c ;
}
and
++i ;
i++ ;
are the same things, because i is only evaluated and the evaluation isn't used
Reason being, in the for loop, I use a pre-increment notation. i is set to the beginning of s, the Boolean condition is checked and it holds true, then i gets incremented and the block executes.
No. i is incremented after the block executes.
I rewrote the program using a post-increment notation and got exactly the same result which confirms my hypothesis. If that is the case, then how are they treated differently in this program?
They're not. Post-increment or pre-increment isn't going to make a blind bit of difference. The difference between those two is in the result of the expression i++, ++i (namely, will it evaluate to the previous value or to the new value?). It does not magically alter the entire flow of an encapsulating control structure. The evaluated result of the increment expression is just thrown away so it doesn't matter what you do as long as you provide an expression that results in incrementing i.
It's like how this:
int main()
{
int x = 5;
int y = 5;
int a = x++;
int b = ++y;
}
will result in different values for a and b because the result of the increment expression is used, whereas the following programs:
int main()
{
int x = 5;
x++;
}
int main()
{
int x = 5;
++x;
}
are identical.
i gets incremented after the block get executed.
Try this:
for(int i = 0; i < 5; ++i )
{
printf("\n %d",i);
}

Is this how postfix increment operator works [duplicate]

This question already has answers here:
Undefined behavior and sequence points
(5 answers)
Closed 9 years ago.
I am solving a problem that reads a set of text lines and prints the longest.
The problem is from K&R "The C programming language" section 1.9. The book provides a solution but I tried to solve it in my own way. The code below works but before I get it to work, I was getting a problem due to the line longestStr[i++] = tmpStr[j++] as I have previously used longestStr[i++] = tmpStr[i++] thinking that i would be incremented once the assignment was done. But that was not the case. Is this how postfix operator normally works?
#include <stdio.h>
#define MAXLINE 100
main()
{
int lineLength = 0, longestLine = 0;
int c, i, j;
char longestStr[MAXLINE];
char tmpStr[MAXLINE];
while((c = getchar()) != EOF)
{
tmpStr[lineLength++] = c;
if(c == '\n')
{
if( lineLength > longestLine)
{
longestLine = lineLength;
i = 0, j = 0;
while(i < lineLength)
{
longestStr[i++] = tmpStr[j++]; // I tried longestStr[i++] = tmpStr[i++] but it gives wrong result
}
}
lineLength = 0;
}
}
printf("Longest line is - %d long\n", longestLine-1);
for(i = 0; i < longestLine-1; i++)
printf("%c", longestStr[i]);
putchar('\n');
}
The postfix increments or decrements are operators that perform the increment or decrement after the use of the variable, such that if you wish to use a integer value to print out and add it at the same time you would use postfix.
int i = 0;
printf("%d",i++);
//prints out 0
Prefix increment/decrement however works in the opposite manner such that it performs the increment/decrement prior to the use of the variable, such that if you wish to increment/decrement a variable before printing it out, you would use prefix
int i = 0;
printf("%d",++i);
//prints out 1
The problem you have is not related to how the postfix operator works, but rather to what you intend to do in the code line which gives you a problem.
As asked in the comments, what is the meaning of the line as you wrote it initially?
longestStr[i++] = tmpStr[i++];
Because the C standard does not specify it, this line can be interpreted in several ways:
longestStr[i] = tmpStr[i+1];
i += 2;
or
longestStr[i+1] = tmpStr[i];
i += 2;
or
longestStr[i] = tmpStr[i];
i += 2;
In every case, you end up with a counter incremented twice, which will mess up your algorithm.
The correct way is to increment the counter in a separate line, or use the working solution (you are providing), which should be compiled down to the same code with any decent compiler.
Note that you should probably check for the counter not going beyond the maximum allowed line size MAXLINE (unless the problem states that this cannot happen with the input, but even in that case, it would be helpful for situations like yours, where the code wrongly increment the counter twice).
try to understand how post fix increment works.
f(i++) is equivalent to the operation 'call f on the current value of i, then increment i'
For example, when you use i++ twice, and initial value of i = 1, a(i++) = b(i++) means, a(1)=b(2) and the value of i after the operation is i=3.
If you want to eliminate one variable in what you are trying to do, you have to make sure you use increment only once. Do it like, a(i)=(b(i); i++
Whereas the postfix increment operator evaluates the original value, it is understandable to think the actual incrementating doesn't happen until sometime down the road. However this is not the case. You should conceptualize postfix as if the incrementing is happening while the original value is being returned.
The bigger issue though is that your statement increments i twice. This means i will increase by two with each iteration of your loop. Futhermore your index values will be off by one from each other, That's because if a variable changes during one part of statement evaluation, those changes become instantly visible to parts of the statement which have not yet evaluated.

Resources