I remember once I've seen somebody writing C++ code like this:
if (something is true)
for (int i = 0; i < max; i++) {
//do something
line 1;
line 2;
line 3;
....
....
}
else
....
It works the same as the following code:
if (something is true) { //note the bracket here
for (int i = 0; i < max; i++) {
//do something
line 1;
line 2;
line 3;
....
....
}
}
else
....
I'm wondering if the compiler treated the for loop block as one line nested within the if clause? Can the multiple lines of code within bracket always be treated as one line? I can't quite understand how does the compiler parse and analyse this.
This is indeed correct code, although it may easily confuse readers. The if-statement considers the first following statement as it's then statement. Code between {} is usually considered a block or compound statement, containing the statements within it. Similarly, the for statement is considered one statement, including the loop body, which is the first statement to follow it (and can again be a block).
They are not really "lines" but rather statements. For instance your
line 1;
line 2;
line 3;
could be rewritten as and would be just as valid as:
line 1; line 2; line 3;
So the compiler is not really looking at lines but rather statements.
A single statement as defined by the grammar is considered either (somewhat simplified):
1) a simple statement terminated by a semicolon (as above)
OR
2) as a statement-block which is one or more simple statements enclosed within brackets {}.
Your first case runs fine because the if statement without brackets considers the next single statement(for loop)as a part of its body to be executed. The body of the for loop is a part of the loop itself.
If there had been no brackets for the loop itself, then only the first statement of the loop would have been executed.
{} defines a compound statement or block.
With the introduction of control structures we are going to have to
introduce a new concept: the compound-statement or block. A block is a
group of statements which are separated by semicolons (;) like all C++
statements, but grouped together in a block enclosed in braces: { }:
From cplusplus.com: Control Structures
The if control structure is defined as follows:
if (condition) statement
That statement can be defined as a single instruction/statement, or a compound statement. Either way, it's the next statement to be executed.
for (;;) statement is a special type of control structure called an iteration structure.
Therefore,
//The control structure is going to apply to the next statement
if (condition)
for (;;) //This for loop is the next statement. It applies to the next statement.
{
//The next statement is a compound statement.
}
Yes if there are no brackets after the if-statement it will just process the next line if the conditions are true. Since the next line was a for statement, it treats it as one command.
Related
I just find out that no matter how many semicolons (if more than 0) the compiler will compile without error
#include <iostream>
int main()
{
int x;
x = 5;;
std::cout << x;;;
}
will just works fine, so why?
It's not an error because the language standard says so. It's OK to have empty statements, they do nothing, and are harmless.
There are times when it's useful:
#ifdef DEBUG
#include <iostream>
#define DEBUG_LOG(X) std::cout << X << std::endl;
#else
#define DEBUG_LOG(X)
#endif
int main()
{
DEBUG_LOG(1);
}
When DEBUG is not defined this will expand to:
int main()
{
;
}
If you couldn't have empty statements that would not compile.
The semicolon is a terminal, a token that terminates something. What exactly it terminates depends on the context.
For example, a semicolon character is at the end of the following parts of the C++ grammar (not necessarily a complete list):
an expression-statement
a do/while iteration-statement
the various jump-statements
the simple-declaration
Note that in an expression-statement, the expression is optional. That's why a 'run' of semicolons, ;;;;, is valid in many (but not all) places where a single one is.
A semicolon terminates a statement, consecutive semicolons represent no operation / empty statement.
No code will be generated for empty statement.
If you have two consecutive semicolons, there is an empty statement between them (just another way of saying: there is no statement between them). So, why are empty statements allowed?
Sometimes you need to use some construct, where the language expects a statement, but you dont want to supply one. For example, a common way to write a infinite loop is like this
for (;;) {
// do something
// ...and break somewhere
}
If c++ didnt allow empty statements, we would have to put some dummy statements instead of naked ;; just to make this work.
When you have ;;; in between you have empty statements. Remember C++ doesn't care about white space.
Shouldn't the following code work mostly like an "if( condition )" statement, up to the obvious misbehaviour when it's inside another loop and the "body" has its own break or continue statements:
for( ; condition ; break ) {
body;
}
This was triggered by a coffee break chat on C++ syntax regarding the assumption that
for( init ; condition ; update ) {
body;
}
is identical to
{
init;
while( condition ) {
body;
update;
}
}
A quick experiment with g++ shows that modelling "if(condition)" with "for(;condition;break)" doesn't compile. So the question is: according to the latest standards, should g++ swallow such construction or is it correct in rejecting it?
It's correct to reject it - the for loop is in the form (see ISO C++ ยง6.5.3):
for ( for-init-statement condition opt ; expression opt) statement
A break is a statement, not an expression.
As mentioned, the workaround is
for( ; condition ; ) {
body;
break;
}
Here's another way without using break:
bool b = false;
for (; condition && !b++; ) { // this usage of operator++ on bool is deprecated
body
}
This is not valid C++, the draft C++ standard in section 6.6.1 The break statement says (emphasis mine):
The break statement shall occur only in an iteration-statement or a switch statement and causes termination of the smallest enclosing iteration-statement or switch statement; control passes to the statement following the terminated statement, if any.
and we can see from the grammar of for from section 6.5 Iteration statements here:
for ( for-init-statement conditionopt; expressionopt) statement
^^^^^^^^^
the statement is the body of the for loop.
EDIT
As dasblinkenlight corrected me, this is not strong enough for the general case. We need to observe that break is a statement not an expression and therefore can not be in the header of a for loop.
It is correct in rejecting it. break cannot be outside the block of code which constitutes the body of the loop itself. That code is not valid C++.
break should be in the body of the for loop:
for( ; condition ; ) {
body;
break;
}
The syntax of a for statement is:
for ( for-init-statement condition[opt] ; expression[opt] ) statement
So the update clause must be an expression, and break not an expression.
This question already has answers here:
How does the Comma Operator work
(9 answers)
Closed 9 years ago.
When I use two variables in a for loop with different conditions two conditions like I have used below i<3,j<2 the for loop is always executing till the second condition fails.
#include<iostream>
#include<conio.h>
using namespace std ;
int main()
{
int i,j ;
for(i=0,j=0;i<3,j<2;i++,j++)
{
cout<<"hello" ;
}
getch() ;
return 0 ;
}
In that code, hello is printed 2 times. Why?
If I use i<3,j<10, "Hello" is printed 10 times. I can't understand why the first condition is being neglected. Is it compiler dependent or something else?
Every thing works normal if I replace with conditions like || (OR) or &&(AND).An other thing is that I cannot initialize i and j in the for loop itself, it is showing me an error, but works fine when I declare variables in C style or one variable outside the for loop, why is it so?
Compiler I have used is Orwell Dev C++.
Thanks in advance.
for(i=0,j=0;i<3,j<2;i++,j++)
is equivalent to
for(i=0,j=0;j<2;i++,j++)
The comma expression takes on the value of the last expression.
Whichever condition is first, will be disregarded, and the second one will be used only.
The for loop consists of:
for(START_STATEMENT; CONDITION_EXPRESSION, LOOP_EXPRESSION) BODY_BLOCK
Where:
START_STATEMENT is any single statement, which may include variable declaration. If you want to declare 2 variables, you can write int i=0, j=0, but not int i=0; int j=0 because the latter are actually 2 statements. Also node, that variable declaration is a part of statement, but cannot be a part of (sub) expression. That is why int i=0, int j=0 would also be incorrect.
CONDITION_EXPRESSION is any single expression that evaluates to a boolean value. In your case you are using a coma operator which has the following semantics: A, B will do:
evaluate A (it will evaluate, not just ignore)
ditch the result of A
evaluate B
return B as the result
In your case: i<3,j<2 you are comparing i<3, you are just ignoring the result of this comparison.
Comma expressions are useful when the instructions have some side effects, beyond just returning a value. Common cases are: variable increment/decrement or assignment operator.
LOOP_EXPRESSION is any single expression that does not have to evaluate to anything. Here you are using the comma expression again, ignoring the result of the left-hand-side. In this case however, you are not using the result anyway, and just using the ++ side effect - which is to increment the values of your variables.
BODY_BLOCK is either a single statement or a block, encapsulated with curly braces.
The above for can be compared to:
{
START_STATEMENT;
while(EXPRESSION) {
BODY_BLOCK;
LOOP_EXPRESSION;
}
}
The c complier always used second condition.
therefore j<2 is used.
use this for loop
for(i=0,j=0;j<10;i++,j++)
this is probably a very noob question but I was what the result of this would be:
int someVariable = 1;
while (callFunction(someVariable));
if (someVariable = 1) {
printf("a1");
} else {
printf("a2");
}
callFunction (int i) {
while (i< 100000000) {
i++;
}
return 0;
}
so when you hit the while loop
while (callFunction(someVariable));
does a thread wait at that loop until it finishes and then to
if(someVariable == 1) {
printf("a1");
} else {
printf("a2");
}
or does it skip and move to the if condition, print "a2" and then after the loop has finished goes through the if condition again?
UPDATE: This isn't ment to be valid c code just psuedo, maybe I didn't word it right, basically what I'm trying to figure out is what the different between a loop like while (callFunction(someVariable)); is vs
while (callFunction(someVariable)){}
i also changed the bolded part in my code i.e ** int someVariable = 1; **, I was doing an endless loop which wasn't my intention.
The code inside a function is executed sequentially, by a single thread. Even if you send an other thread to your function it will execute it sequentually as well.
This is true to 99% of programming languages now days.
UPDATE
basically what I'm trying to figure out is what the different between a loop like while (callFunction(someVariable)); is vs while (callFunction(someVariable)){}
No practical difference. ; delimits an empty statement, { } is a scope without statements. Any compiler can be expected to produce identical code.
Of course, if you want to do something in each iteration of the loop, { } creates a "scope" in which you can create types, typedefs and variables as well as call functions: on reaching the '}' or having an uncaught exception, the local content is cleaned up - with destructors called and any identifiers/symbols use forgotten as the compiler continues....
ORIGINAL ANSWER
This...
callFunction(int i){
while (i< 100000000){
i++;
}
return 1;
}
...just wastes a lot of CPU time, if the compiler's optimiser doesn't remove the loop on the basis that it does no externally-visible work - i.e. that there are no side-effects of the loop on the state of anything other that "i" and that that's irrelevant because the function returns without using i again. If always returns "1", which means the calling code...
while (callFunction(someVariable));
...is equivalent to...
while (1)
;
...which simply loops forever.
Consequently, the rest of the program - after this while loop - is never executed.
It's very hard to guess what you were really trying to do.
To get better at programming yourself - understanding the behaviour of your code - you should probably do one or both of:
insert output statements into your program so you can see how the value of variables is changing as the program executes, and whether it's exiting loops
use a debugger to do the same
Your code contains an endless loop before any output:
while (callFunction(someVariable));
Did you mean for the ; to be there (an empty loop), or did you
mean something else? Not that it matters: callFunction
always returns 1, which is converted into true. (If you
really want the loop to be empty, at least put the ; on
a separate line where it can be seen.)
If you do get beyond the while (because you modify some code
somewhere), the if contains an embedded assignment; it's
basically the same as:
if ( (someVariable = 1) != 0 )
Which is, of course, always true. (Most C++ compilers should
warn about the embedded assignment or the fact that the if
always evaluates to true. Or both.)
If your loop completes (it would be sequentially yes, if you fix it), it will print 'a1', since you're doing an assignment in the if, which will always return 1, which evaluates to 'true' for conditionals.
My guess is it just made parsing easier, but I can't see exactly why.
So what does this have ...
do
{
some stuff
}
while(test);
more stuff
that's better than ...
do
{
some stuff
}
while(test)
more stuff
Because you're ending the statement. A statement ends either with a block (delimited by curly braces), or with a semicolon. "do this while this" is a single statement, and can't end with a block (because it ends with the "while"), so it needs a semicolon just like any other statement.
If you take a look at C++ grammar, you'll see that the iteration statements are defined as
while ( condition ) statement
for ( for-init-statement condition-opt ; expression-opt ) statement
do statement while ( expression ) ;
Note that only do-while statement has an ; at the end. So, the question is why the do-while is so different from the rest that it needs that extra ;.
Let's take a closer look: both for and regular while end with a statement. But do-while ends with a controlling expression enclosed in (). The presence of that enclosing () already allows the compiler to unambiguously find the end of the controlling expression: the outer closing ) designates where the expression ends and, therefore, where the entire do-while statement ends. In other words, the terminating ; is indeed redundant.
However, in practice that would mean that, for example, the following code
do
{
/* whatever */
} while (i + 2) * j > 0;
while valid from the grammar point of view, would really be parsed as
do
{
/* whatever */
} while (i + 2)
*j > 0;
This is formally sound, but it is not really intuitive. I'd guess that for such reasons it was decided to add a more explicit terminator to the do-while statement - a semicolon. Of course, per #Joe White's answer there are also considerations of plain and simple consistency: all ordinary (non-compound) statements in C end with a ;.
It's because while statements are valid within a do-while loop.
Consider the different behaviors if the semicolon weren't required:
int x = 10;
int y = 10;
do
while(x > 0)
x--;
while(x = y--);
While I don't know the answer, consistency seems like the best argument. Every statement group in C/C++ is either terminated by
A semicolon
A brace
Why create a construct which does neither?
Flow control statement consistency
Considering consistency...
if (expr) statement;
do statement; while (expr);
for (expr; expr; expr) statement;
while (expr) statement;
...all these flow-control constructs, end with a semicolon.
But, countering that we can note that of the block-statement forms, only do while is semicolon delimited:
if (expr) { ... }
do { ... } while (expr);
for (expr; expr; expr) { }
while (expr) { }
So, we have ';' or '}', but never a "bare" ')'.
Consistency of statement delimiters
We can at least say that every statement must be delimited by ; or }, and visually that helps us distinguish statements.
If no semicolon were required, consider:
do statement1; while (expr1) statement2; do ; while (expr2) statement3; while (expr3) statement4;
It's very difficult to visually resolve that to the distinct statements:
do statement1; while (expr1)
statement2;
do ; while (expr2)
statement3;
while (expr3) statement4;
By way of contrast, the following is more easily resolved as a ; immediately after a while condition tells you to seek backwards for the do, and that the next statement is unconnected to that while:
do statement1; while (expr1); statement2; do ; while (expr2); statement3; while (expr3) statement4;
Does it matter, given people indent their code to make the flow understandable? Yes, because:
people sometimes make mistakes (or have them transiently as the code's massaged) and if it visually stands out that means it will be fixed more easily, and
macro substitutions can throw together lots of statements on one line, and we occasionally need to visually verify the preprocessor output while troubleshooting or doing QA.
Implications to preprocessor use
It's also worth noting the famous preprocessor do-while idiom:
#define F(X) do { fn(X); } while (false)
This can be substituted as follows:
if (expr)
F(x);
else
x = 10;
...yields...
if (expr)
do ( fn(x); } while (false);
else
x = 10;
If the semicolon wasn't part of the do while statement, then the if statement would be interpreted as:
if (expr)
do-while-statement
; // empty statement
else
x = 10;
...and, because there are two statements after the if, it's considered complete, which leaves the else statement unmatched.
C is semicolon-terminated (whereas Pascal is semicolon-separated). It would be inconsistent to drop the semicolon there.
I, frankly, hate the reuse of the while for the do loop. I think repeat-until would have been less confusing. But it is what it is.
In C/C++ whitespace don't contribute to structure (like e.g. in python). In C/C++ statements must be terminated with a semicolon. This is allowed:
do
{
some stuff; more stuff; even more stuff;
}
while(test);
My answer is that, the compiler may get confusion, when we didn't include the semicolon in the termination of do.....while(); loop. Without this it is not clear about:
when the do ends?
If the while may a separate loop followed immediately after do loop.
That's why we include semicolon in the end of do......while loop, to indicate the loop is terminating here if the condition is false.