Adding a `;` at the end of while loop - c

#include<stdio.h>
int main()
{
int i=5;
while(i--)
{
printf("%d\n",i);
};
printf("Out of loop\n");
return 0;
}
This code works fine! Does ; at the end of a loop not mean anything?
So even if we add it, we don't have any problems? Just curious! I think adding ; at the end of a loop doesn't make any sense.

It "works", but it's an empty statement so it changes the structure of your program.
Consider this:
if (foo())
while (bar())
{
foo_some_more()
}
else
{
do_something_about_it();
}
The above works since the while is a single statement, and thus the else is still able to "find" the if properly. If you add a semi-colon after the while-loop's closing brace, you break that structure and it will no longer compile.
So, although empty statements can look harmless, they are not so they really should be avoided. Plus: they add pointless confusion to the code, of course.

The ; here is considered as an empty statement or null statement.
Sample
int i = 0;;
For more information, you can check this question.
Word of Caution: Don't consider this as a thumb rule. There are cases where the representation may appear same, but they are not null statement but part of a syntax. Example: do..while loop

A superfluous ; is an empty statement and is redundant in this particular instance.
One instance where you're required to use an empty statement is in a switch to a final branch that does nothing:
switch (expression)
{
case 1:
/*Some statements here or empty*/
case 2:
; /*A statement is required between here and the closing brace
An empty statement will suffice.*/
}
You ought to avoid using superfluous empty statements; they can emit bugs (particularly if you enclose your code in if statements during a refactoring effort), and older compilers will complain. Using excess semicolons in macros is particularly pernicious.

These are Perfectly Valid, They are called Empty statements,They do nothing.
int main()
{
;
;
;
;
{
}
return 0;
}

As stated by various users above, the relevant semi-colon is an empty statement and has no effect.
This however is a slightly different story:
#include <stdio.h>
int main()
{
int i=5;
while(i--); //<--- Put the semi-colon here and see what you get.
{
printf("%d\n",i);
}
printf("Out of loop\n");
return 0;
}

#include<stdio.h>
int main()
{
int i=5;
while(i--)
{
printf("%d\n",i);
}/*blank statement*/;
printf("Out of loop\n");
return 0;
}
it's just a blank statement.
above The braces itself tells end of the block so then it would treat the ; as blank stament

Related

Iterative Statements

So, I have been studying iterative statements for a report. While I was reading, I came across the developmental history of definite iteration and eventually learn the for loop. We know that the syntax for the for loop in C,C++, and java is
for (expression1; expression2; expression3)
statement
And it says here that we can omit any of the expression and that it is legal to have a for loop that look like this
for (;;)
My question is how does that work? I cant find any more resources for this one.
A for loop declared as:
for (init-statement; condition; iteration-expression) body;
Is equivalent to:
init-statement;
while (condition) {
body;
iteration-expression;
}
It's easy to see how init-statement or iteration-expression could be omitted. If the condition is omitted, it is assumed to be true.
A reasonable resource that explains this is the Explanation section of the for loop documentation at cppreference.com.
Basically, for (;;) is legal, but you will need to put something inside the body of that for loop, otherwise the loop will never stop.
int counter = 0;
int limit = 5;
for (;;) {
if (counter > limit) break;
counter++;
}

C: why are extra semicolons OK?

#include <stdio.h>
int main() {
int a = -1, b = -10, c = 5;
if (a > b)
printf("Hello World");
else
printf("Get out World");;;;;;
}
Can anybody tell me why line number 8 still works, with multiple semicolons?
An empty statement is legal in C. Since ; is the statement terminator, multiple ; are syntactically valid. Sometimes this is even useful: such as the for (;;) {/*code here*/} idiom.
(Although some compilers will warn you in appropriate instances).
Do note that, conceptually at least, the excess ; in that line are not part of the if block.
Your program just has a sequence of empty statements at the end of the main function. It is parsed as this:
#include <stdio.h>
int main() {
int a = -1, b = -10, c = 5;
if (a > b)
printf("Hello World");
else
printf("Get out World");
;
;
;
;
;
}
Note that int main() should be written int main(void) and it should return an int value, for example 0. C99 makes this return 0; implicit, but it is considered bad style and it is indeed less portable to omit it.
Extra semicolons in general are not "OK".
For example, changing your code slightly:
#include <stdio.h>
int main() {
int a = -1, b = -10, c = 5;
if (a > b)
printf("Hello World");;;;;;
else
printf("Get out World");
}
That won't even compile.
Another example, and this one does compile:
...
int done = 0;
...
while ( !done );
{
...
done = 1;
}
...
;;;;; are empty statements. They are allowed in C.
It's a null statement which you have after the printf() statment. Having more than one semi-colons is allowed.
C11, ยง6.8.3, 4
A null statement (consisting of just a semicolon) performs no
operations
Well, the ; semicolon in C is a statement terminator, which means that you cannot put it where you like, only at the end of a statement.
The null statement (one that does nothing) is valid in C, which allow you to write things as the one you post, and things like:
while((data = do_read(...)) != NULL); /* skip input until EOF */
that should be more visible written as (a single semicolon is too small to be skipped in a quick read):
while((data = do_read(...)) != NULL) continue;
which looks better as you'll never think that the next line is inside the loop.
By the way, if you write something like:
if (a > b); /* <====== LOOK at this semicolon */
printf("Hello World");;;;;;
else
printf("Get out World");
it will not compile, as that means if a greater than b just do nothing and that's a good valid sentence in C. By contrast you'll get an error several lines later, when the compiler gets to the else token and cannot match it to an if statement (remember, when you used the ;, you finished the ifstatement)
That also happens to occur with the group of semicolons you put after the printf("Hello World"); statement (the first semicolon terminates it, and also as the next token is not an else but a ;, also terminates the if statement).
The statements in the example above are:
if (a > b); /* if a greater than b do nothing */
; /* do nothing */
; /* ... */
; /* ... */
; /* ... */
; /* do nothing */
else /* ERROR, else cannot begin a statement */
....
Here, as you got a syntax error from the compiler, you cannot have a good C program so you'll not get further analysing (the compiler tries to recover and continue parsing past that point, but you can have new errors originating of the new condition, or fake errors)
As we know, semicolon (;) works as a statement terminator. In the Line no.8 the first semicolon terminates the statement under else and the next semicolon terminates the empty statement, and so on.

How are if statements in C syntactically unambiguous?

I don't know a whole lot about C, but I understand the basics and as far as I can tell:
int main() {
if (1 == 1) printf("Hello World!\n");
return 0;
}
and
int main() {
if (1 == 1)
printf("Hello World!\n");
return 0;
}
and
int main() {
if (1 == 1) {
printf("Hello World!\n");
}
return 0;
}
are all precisely syntactically equivalent. The statement is true; the string is printed; the braces are (apparently) optional.
Sometimes, especially here on SO, I see something like the following:
int main() {
if (1 == 1)
printf("one is one\n");
printf("is this inside the if statement??/who kn0WS\n");
return 0;
}
By the power vested in CodeGolf, I have been led to believe that C is whitespace-agnostic; the lexical analyser breaks the tokens up into their component parts and strips whitespace outside strings.
(I mean, the whole reason for the semicolons-on-every-statement-thing is so the parser can strip \n, \t, literal spaces and still know where each statement ends, right??)
So how is it possible to unambiguously parse the previous bit of code (or perhaps someone can come up with a better example of what I mean), if whitespace is to be disregarded?
If C programmers want to write in whitespace-dependent Pythonic syntax, why do they write C, and why is it taught wherever C is taught that it's okay to write lexically ambiguous (both to me, a programmer, and the computer) statements like this?
if (1 == 1)
printf("one is one\n");
printf("is this inside the if statement??/who kn0WS\n");
The second printf() should never execute inside the if statement.
The reason being that the previous line ends with a semicolon, which indicates the end of the if-block to execute.
(I mean, the whole reason for the semicolons-on-every-statement-thing
is so the parser can strip \n, \t, literal spaces and still know where
each statement ends, right??)
So how is it possible to unambiguously parse the previous bit of code
(or perhaps someone can come up with a better example of what I mean),
if whitespace is to be disregarded?
Parsing example:
if (1 == 1) // if - ( and ) - statements (or block) follow, skip all whitespace
// no { found -> single statement, scan until ; (outside quotes / comments)
printf("one is one\n"); // ; encountered, end of if-block
Without braces, only one statement belongs to the if-block.
But, as said already, it's a good habit to use braces. If you later add a statement (a quick temporary printf() for example), it will always be inside the block.
Special case:
int i = 0;
while(i++ < 10);
printf("%d", i);
Here printf() will only execute once. Mark the ; at the end of while().
In case of an empty statement, it's better to use:
while(i++ < 10)
;
to make the intention clear (or, as an alternative, an empty block {} can be used as well).
In C, an if statement takes exactly statement after the truth expression, regardless of indentation. Normally this statement is indented for clarity, but C ignores indentation. In any case, there is no amiguity in any of your examples.
What is ambiguous, in C and in many other languages, is the "dangling else". For instance, suppose you have a nested if statement with a single else after the second one. It could group as:
if (expr)
if (expr)
statement
else
statement
Or it could group as:
if (expr)
if (expr)
statement
else
statement
The only difference between these two is how they're indented, which C ignores. In this case, the ambiguity is resolved by using the first interpretation, i.e., the else statement binds to the nearest preceding if statement. To achieve the second interpretation, curly braces are needed:
if (expr) {
if (expr)
statement
}
else
statement
However, even in the first case, it's a good idea to include the curly braces, even though they aren't required:
if (expr) {
if (expr)
statement
else
statement
}
tl;dr The only ambiguity is in how difficult it is for a human to read. From the compiler's perspective, the syntax is perfectly unambiguous.
There are only two (compilable and syntactically acceptable) possibilities after an if statement:
Braces, as in
if(x) {
DoFoo();
}
// or
if(x) { DoFoo(); }
In this case, whatever is in the {...} will execute if the condition is met.
No braces, as in
if(x)
DoFoo();
// or
if(x) DoFoo();
In this case, only the next statement will execute if the condition is met.
You are correct that C is whitespace-agnostic. As a result, omitting the braces can lead to some tricky bugs. For example, in this code, DoBar() will execute whether or not the condition is met:
if(x)
DoFoo();
DoBar();
Inconsistent use of braces can also easily result in invalid code. For example, this looks valid (at a glance) from a human perspective, but it's not:
if(x)
DoFoo();
DoBar();
else
DoBaz();
None of the examples you posted are ambiguous from the compiler's perspective, but the no-braces versions are confusing from a human perspective. Leaving out the braces frequently leads to hard-to-find bugs.
Without braces it is just the next statement after the if. The whitespace does not matter
It is good practice and makes life easier to always use the braces. Good indentation as well. Code is then easy to read and does not lead to errors when people add/remove statements after the if
Readability is the only ambiguity in the statement:
if (1 == 1)
printf("one is one\n");
printf("is this inside the if statement??/who kn0WS\n");
The only time the first statement following the if(...) statement should execute, is if it is evaluated TRUE.
Braces, {...} help to remove readability ambiguities,
if (1 == 1)
{
printf("one is one\n");
}
printf("is this inside the if statement??/who kn0WS\n");
but the syntax rules are still the same.
Opinions vary, but I always choose to use braces.
Not using them is fine at the time code is written. But down the road, you just know someone will come along and add another statement under the first and expect it to be executed.
In general, in a statement or a loop with a single instruction, the curly brackets are optionals; instead, if you have two or more instructions you have to add them.
For example :
for(i = 0; i < 2; i++)
for(j = 0; j < 4; j++)
If(...)
printf(..);
else
printf(..);
Is equivalent to :
for(i = 0; i < 2; i++)
{
for(j = 0; j < 4; j++)
{
If(...)
{
printf(..);
}
else
{
printf(..);
}
}
}
As you may note this is more something related to indentation of the code. Personally I don't use curly brackets if I have a single instruction as doing that will make your code shorter and cleaner.
Another reason to use braces is that a simple typo can bite you hard:
#include <stdio.h>
int main(void) {
if (0 == 1)
printf("zero is one\n"),
printf("is this inside the if statement?? /who kn0WS\n");
return 0;
}
Look carefully...

In C why do you need a statement after a goto label?

I am writing some C code and in my code I have two nested loops. On a particular condition I want to break out of the inner loop and continue the outer loop. I tried to achieve this using a label at the end on the outer loop's code and, on the condition, goto that label. However gcc gives an error that I cannot have a label at the end of a compound statement. Why not?
Note 1: This is not a switch statement and that question has been answered elsewhere.
Note 2: This is not a question about style and whether I should or should not be using goto statements or conditional variables instead.
EDIT: People have asked for an example and I can give a slightly facile example of checking if an array is a subarray of another array
int superArray[SUPER_SIZE] = {...}, subArray[SUB_SIZE] = {...};
int superIndex, subIndex;
for (superIndex=0; superIndex<SUPER_SIZE-SUB_SIZE; superIndex+=1)
{
for (subIndex=0; subIndex<SUB_SIZE; subIndex+=1)
if (superArray[superIndex+subIndex] != subArray[subIndex])
goto break_then_continue;
// code that executes if subArray is a sub array
break_then_continue:
}
In the standard it's explicitly said that labels belong to a statement, therefore a simple semicolon (;) after your label can circumvent the problem you are running in to, since that counts as a statement.
There is even an example of the use of an "empty"1 statement in 6.8.3/6.
EXAMPLE 3 A null statement may also be used to carry a label just
before the closing } of a compound statement
while (loop1) {
/* ... */
while (loop2) {
/* ... */
if (want_out)
goto end_loop1;
/* ... */
}
/* ... */
end_loop1: ;
}
1 In the standard this is referred to as a null statement.
6.8.1 Labeled statements
Syntax
1 labeled-statement:
identifier : statement
case constant-expression : statement
default : statement
Notice that statement isn't optional in the above quotation.
open-std.org: n1124.pdf
You simply need to write:
label: ;
The semi-colon is an empty statement. You need it because the language is defined like that; you need to go to a statement, even if it is an empty one.
for (int i = 0; i < N; i++)
{
for (int j = 0; i < M; j++)
{
...
if (some_condition)
goto continue_loop1;
...
}
continue_loop1: ;
}
You can argue about the indentation on the label.
The label should point to a statement.
C mandates this:
(C99, 6.8.1 Labeled statements p4) "
Any statement may be preceded by a prefix that declares an identifier as a label name."
In your case you can use a null statement:
void foo(void)
{
goto bla;
bla:
;
}
Null statements perform no operation.
Or you can also use a compound statement (a block) if you have declarations:
void foo(void)
{
goto bla;
bla:
{
int x = 42;
printf("%d\n", x);
}
}

Example of a while loop that cannot be replaced by a for loop

The question basically is similar to what is posted here Example of a While Loop that can't be a For Loop except that there isn't one such example where a certain program using the while loop cannot be replaced by the for loop because of its limitations.
An example is
i=0;
while(i<10)
{
continue;
i=i+2;
}
and
for(i=0;i<10;i++)
{
continue;
i++;
}
In the for loop the continue doesn't stop the increment. I wanted to see something different.
It is obvious that such does not exist, because any while() loop of the form:
while (expression) { }
can be replaced with
for (;expression;) { }
The same is not true of do { } while () loops.
There's no such situation.
In particular, any
while( condition )
may be replaced by
for(; condition ;)
to achieve identical behavior.

Resources