Any difference between these two while loops? - c

while ((R_SPI2SR & B_SPIF) != B_SPIF)
{
SERIAL_SERVICE_WDOG;
};
while ((R_SPI2SR & B_SPIF) != B_SPIF)
{
SERIAL_SERVICE_WDOG;
}
I like to know what is the purpose in putting semicolon..

The semicolon after the first loop is not a part of that loop at all. It is interpreted as a completely independent empty statement that sits between the loops. I.e. your actual loops are seen as absolutely identical by C language.

The statement executed by the while loop is the compound statement inside the curly braces. The semicolon is just a gratuitous empty statement. You could have written this loop as:
while ((R_SPI2SR & B_SPIF) != B_SPIF)
SERIAL_SERVICE_WDOG;
since the compound statement just has a single statement inside it, or as
while ((R_SPI2SR & B_SPIF) != B_SPIF)
{
SERIAL_SERVICE_WDOG;;;;;;;;;;;;;;;
};;;;;;;;;;;;;;
which of course is awful style.
An empty statement is used when you have a loop that needs no body.
/* Throw away remaining characters up to the end of line. */
while ( ( c = getchar() ) != '\n')
;
You want to watch out for the classic error of ending a loop prematurely:
int i = 1;
int j = 1;
while ( i < 10 ); /* The semicolon here ends the loop... */
j *= i++; /* ... so this statement is only executed once. */
Unnecessary semicolons are just clutter, so you should never use them.

the only different in the code is the additional semicolon.
but the compiled assembly are the same.

Related

What is a null statement in C?

I want to know exactly, what is a null statement in C programming language? And explain a typical use of it.
I found the following segment of code.
for (j=6; j>0; j++)
;
And
for (j=6; j>0; j++)
From the msdn page:
The "null statement" is an expression statement with the expression missing. It is useful when the syntax of the language calls for a statement but no expression evaluation. It consists of a semicolon.
Null statements are commonly used as placeholders in iteration statements or as statements on which to place labels at the end of compound statements or functions.
know more: https://msdn.microsoft.com/en-us/library/1zea45ac.aspx
And explain a typical use of it.
When you want to find the index of first occurrence of a certain character in a string
int a[50] = "lord of the rings";
int i;
for(i = 0; a[i] != 't'; i++)
;//null statement
//as no operation is required
A null statement is a statement that doesn't do anything, but exists for syntactical reasons.
while ((*s++ = *t++))
; /* null statement */
In this case the null statement provides the body of the while loop.
or (disclaimer: bad code)
if (condition1)
if (condition2)
dosomething();
else
; /* null statement */
else
dosomethingelse();
In this case the inner else and null statement keeps the outer else from binding to the inner if.
From C11, §6.8.4.1, 6.8.3 Expression and null statements:
A null statement (consisting of just a semicolon) performs no
operations.
The standard also provides a couple of common uses of it:
EXAMPLE 2 In the program fragment
char *s;
/* ... */
while (*s++ != '\0')
;
a null statement is used to supply an empty loop body to the iteration
statement.
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: ;
}
A null statement doesn't DO anything, hence the solo ';'
so....this code block will do nothing 10x in C/C++
for(int i = 0; i < 10; i++){//execute the following 10 times
;//nothing aka "null statement"
}//end for
Sometimes the null statement serves. In the "old days" the math hardware might not return an integer value when you needed one, such as returning 0.999... as sin(pi / 2), (that is sin(90 degrees)).
int i, j, k;
i = something;
for(j = 1; (2 * j) <= i; j *= 2);
Computes in j the largest integer power of 2 less than i. Not very efficient for large i but useful if you could not trust Log functions to return an exact integer value.
My C++ compiler does not accept the null statement as a function body, but does accept the "empty statement" which I think is just an empty statement block "{}".
Whether C or java, null has a special significance.
Whenever there is a need of re-intializing of values to variavle, null serves the purpose.
If there is a String i, and we want it to add a char value through a loop, then first we have to intialize i with null.

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...

why there is semicolon after loop while();

I am reading a code of my friend an I see this:
#include <stdio.h>
#include <conio.h>
void main()
{
char string1[125], string2 [10];
int i, j;
printf("\nstring 1: ");
gets(string1);
printf("\nNstring2 : ");
gets(string2);
i = 0;
while (string1[i] != 0)
{
j = 0;
while (string1[i++] == string2[j++] &&string1[i-1] != 0 && string2[j-1] != 0)
;//i dont know what it mean and why we can put ;after while loop
if (string1[i-1] != 0 && string2[j-1] == 0)
printf("\nfound at position %d", i-j);
}
getch();
}
why we can put ; after while loop , anyone can help?
The ; is just a null statement, it is a no op but it it the body of the while loop. From the draft C99 standard section 6.8.3 Expression and null statements:
A null statement (consisting of just a semicolon) performs no operations.
and a while statement is defined as follows from section 6.8.5 Iteration statements:
while ( expression ) statement
So in this case the statement of the while loop is ;.
The main effect of the while loop is here:
string1[i++] == string2[j++]
^^^ ^^^
So each iteration of the loop increments i and j until the whole condition:
string1[i++] == string2[j++] &&string1[i-1] != 0 && string2[j-1] != 0
evaluates to false.
Usually, in a while loop, you have initialization, a comparison check, the loop body (some processing), and the iterator (usually either an addition of an index, or a pointer traversal e.g. next), something like this:
index = 0 // initialization
while(index < 4) { // comparison, loop termination check
printf('%c\n', mystring[index]); // Some processing
index += 1; // iterate to next loop
}
Without at least the last item, you won't ever exit the loop, so normally the loop body has more than one statement in it. In this case, they use post-increments like this:
while (string1[i++] == string2[j++]);
This does the comparison (the ==) and the iteration (the post-increment ++) in the comparison statement itself, and has no body, so there's no reason to add any other statements. A blank loop body can be represented by just a semicolon.
Semicolon is like empty instruction. If we don't put any instruction after while or use loop while with {} we must use semicolon to tell compiler that all we want from while loop is doing this empty instruction.
That is called a semicolon. In programming standards, the ; signifies an end of statement, or in this case that it is a null statement. It is effectively a non operation in the body of the while loop, so it is not actually doing anything.

Why is 'continue' statement ignoring the loop counter increment in 'while' loop, but not in 'for' loop?

Why does it tend to get into an infinite loop if I use continue in a while loop, but works fine in a for loop?
The loop-counter increment i++ gets ignored in while loop if I use it after continue, but it works if it is in for loop.
If continue ignores subsequent statements, then why doesn't it ignore the third statement of the for loop then, which contains the counter increment i++? Isn't the third statement of for loop subsequent to continue as well and should be ignored, given the third statement of for loop is executed after the loop body?
while(i<10) //causes infinite loop
{
...
continue
i++
...
}
for(i=0;i<10;i++) //works fine and exits after 10 iterations
{
...
continue
...
}
Because continue goes back to the start of the loop. With for, the post-operation i++ is an integral part of the loop control and is executed before the loop body restarts.
With the while, the i++ is just another statement in the body of the loop (no different to something like a = b), skipped if you continue before you reach it.
The reason is because the continue statement will short-circuit the statements that follow it in the loop body. Since the way you wrote the while loop has the increment statement following the continue statement, it gets short-circuited. You can solve this by changing your while loop.
A lot of text books claim that:
for (i = 0; i < N; ++i) {
/*...*/
}
is equivalent to:
i = 0;
while (i < N) {
/*...*/
++i;
}
But, in reality, it is really like:
j = 0;
while ((i = j++) < N) {
/*...*/
}
Or, to be a little more pedantic:
i = 0;
if (i < 10) do {
/*...*/
} while (++i, (i < 10));
These are more equivalent, since now if the body of the while has a continue, the increment still occurs, just like in a for. The latter alternative only executes the increment after the iteration has completed, just like for (the former executes the increment before the iteration, deferring to save it in i until after the iteration).
Your increment of i is after continue, so it never gets executed
while(i<10) //causes infinite loop
{
.........
continue
i++
......
}
In any loop, continue moves execution back to the top of the loop, not executing any other instructions after the continue statement.
In this case, the for loop's definition is always executed (per standard C), whereas the i++; statement is NOT executed, because it comes AFTER the continue statement.
Because the third part of the for is always executed.
continue statement jumps the control to the end of the statements in current iteration of loop i.e. it skips the execution of the statements in the current iteration and moves to the next iteration of the loop.
With while loop, continue statement causes control to reach the end of statements (including increment statement), thus causing loop to continue forever.
With for loop, continue statement jumps the control to end of statement and excutes the increment statement (In for loop, increment statement is considered seperate from the statments written within the body of the loop).
for loop holds condition statements and increment, so when the condition is satisfied it goes to execute the statement inside for loop,but if write continue statement than it will again reached to first line of for loop i.e. increment and checking of condition statement, if satisfied than again comes in for execution.
For while loop it just checks the condition statement and if condition satisfied it goes for the execution of statements in the while loop.
so continue will not execute any line after it.and hence your condition satisfied every time and goes for the infinite loop.
continue bypasses the rest of the block and begins again at the top of the block if the conditional of the loop is met.
The next question is: "What do I do, then?"
There are two answers I can think of.
Example:
void foo ()
{
size_t i = 0;
do
{
/*...*/
if ( /*...*/ )
{
/*...*/
continue;
}
/*...*/
i++;
} while ( /* loop conditional */ );
}
Solution #1: Manually Increment
void foo ()
{
size_t i = 0;
do
{
/*...*/
if ( /*...*/ )
{
/*...*/
i++;
continue;
}
/*...*/
i++;
} while ( /* loop conditional */ );
}
Solution #2: A uniquely valid application of goto*
void foo ()
{
size_t i = 0;
do
{
/*...*/
if ( /*...*/ )
{
/*...*/
goto foo_next;
}
/*...*/
foo_next:
i++;
} while ( /* loop conditional */ );
}
goto is valid in this case because incrementation in two places is technically the same instruction. This solution is especially relevant when the per-iteration-volatile variables are more complex; such as, setting multiple variables or modifying a value with an equation or function.
In the event of a single increment or decrement statement, Solution #1 may prove favorable; however, it should be noted that: if the code is modified after such an implementation, one must remember to update both instances of the statement (which may be prone to bugs, especially if the modifications take place after an extended period of time**). Therefore, I highly reccomend Solution #2.
*Some consider any and all use of goto bad practice. I recommend you decide for yourself, and leave you this: google for "c goto bad"
**A comment reminding of this necessity may suffice, but — if my advice has been followed — the per-iteration-volatile variables in are restricted to a single statement. And I quote:
There is never a reason to comment a single line
-Linus Torvalds (source: http://yarchive.net/comp/linux/coding_style.html)

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);
}
}

Resources