C: why are extra semicolons OK? - c

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

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.

Adding a `;` at the end of while loop

#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

Undeclared identifier for [i] when creating variables dynamically

This following code is supposed to encrypt a sentence using the ceasers cipher, it is still WIP i haven't accounted for spaces, lower case letters etc etc.
int main(int argc,string argv[])
{
int k = atoi(argv[1]);
string value = GetString();
int n = strlen(value);
for(int i = 0;i<n; i++);
{
char temp = value[i];
int conv = temp - (int)'A';
int cipher = (conv + k)%26;
char final = cipher + (int)'A';
printf("%c\n",final);
}
}
I get
caeser.c:15:23 use of undeclared identifier i.
which is on the line char temp = value[i];
Remove the semicolon at the end of the for line:
for(int i = 0;i<n; i++);
Declaring int i there makes it local to the for block, but because of the semicolon that is an empty block.
So in the following code block (between the { }) i is not declared because it does not belong to the for.
This will also fix the program not executing the body of the for more than once (which it would, if it compiled). If this had compiled the for loop would have looped until n but not execute anything. Then after that the code between the curly braces would have been executed with i == n (assumed that i is then visible to that code block). So your code would always execute with temp == '\0' (the terminating null in value) and always print the same cipher value.
ENCORE: (as explained in the comments, but here for completeness' sake)
The casts of character-literals to ints (int conv = temp - (int)'A';) are unnecessary for two reasons:
Contrary to what may seem intuitive character-literals are ints, not chars (this is different in C++, I believe)
But even if 1. weren't the case, a char is always smaller than an int and will thus always fit inside an int so it can safely be promoted.
Your problem is here:
for(int i = 0;i<n; i++);
^
The ; ends your for loop, it runs n times but performs no operation since the ; just ends a null statement. So the {} afterward is just a compound statement with it's own scope which does not include the declaration of i:
{
char temp = value[i]; // i does not exist here since it declared in for loop
// and it's scope ends with the for loop
//...
}
The C99 draft standard tells us that what you have after the for is a statement expression, section 6.8.3 Expression and null statements has the following grammar for expression statements:
expression-statement:
expressionopt ;
and in paragraph 3 tells us that the empty statment is just a null statement:
A null statement (consisting of just a semicolon) performs no operations.

C preprocessor conditional statement output

I have this code but not able to understand the output. Can someone help out to know the behaviour
#include<stdio.h>
int main(){
int a =1;
#if(a==0)
printf("equal");
#else if
printf("unequal");
#endif
return -1;
}
Output comes out to be equal. Strange for me.
Also if i change the if condition to a==2, the output comes unequal
If i try to print value of 'a' inside 'if' block something like
#if(a==0)
printf("value of a: %d",a);
output comes out to be value of a: 1
Please some one explain the output.
The a in the preprocessor directive refers to preprocessor definitions, not variables in your program. Since a is not #defined, its value is effectively 0 for the purposes of #if.
The preprocessor directives (the lines starting with #) are dealt with at compile time, not at runtime. The a in that #if is not the same as the a variable you declared. The preprocessor just replaces it with 0, since there is no #define a statement anywhere. The variable a is unused in your program. If you do use it, like in the printf statement you show, it will get printed as expected - a value of 1 that you assigned to it.
#include<stdio.h>
int main(){
int a =1;
#if(a==0)
printf("equal");
#else if
printf("unequal");
#endif
return -1;
}
which you pass to the compiler will first go through the preprocessor whose output is then sent as an input to the compiler; the preprocessor will send
#include<stdio.h>
int main(){
int a =1;
printf("equal");
return -1;
}
to the compiler, which is the reason you see equal always. The reason is since a as a macro is undefined, the first condition is true, there by leading to only passing that statement on to the compiler. If you try adding #define a 1 next to the include directive, then you'll always see unequal as an output; but these changes affect only the compile time macro a and not the runtime variable a (both are entirely different).
All this because preprocessor is concerned only with compile-time constructs. What you really need may be
#include<stdio.h>
int main(){
int a =1;
if(a == 0)
printf("equal");
else
printf("unequal");
return 0;
}
Aside: Return 0 when you're program is successful, returning negative values from main usually means some error state termination of your program.

assignment works as a condition

Consider the following Code,
int i;
while(i=0)
printf("Hello");
Now Generally speaking i=0 is an assignment and not a condition for while to check.
But the GCC compiler lets it go with a warning and even evaluates it correctly (does not execute the print statement).
Why? I usually would do with parenthesis for the truth value but my juniors feel that I am wrong and there is no real reason for the parenthesis in this!
EDIT: Zeroing down on the 'actual' doubt, Please consider the following test case
int callme(){
return 0;
}
int main(int argc,char*argv[]){
int c;
while(c = callme()){
printf("Calling...\n");
}
return 0;
}
The expression i = 0 does 2 things:
Has the side effect of storing o in i
Yields the value 0
I usually would do with parenthesis for the truth value but my juniors
feel that i am wrong and there is no real reason for the parenthesis
in this
It's usually a hint to the compiler meaning "I actually want this, I didn't forget a =, shut up".
For your specific case there's no reason to write if (i = 0): you already know what if (0) does. But it's pretty useful when used as:
if ((i = some_function()))
...
i=0 is always an assignment (unless you have it as part of int i = 0; where it is an initialization). But any non-void expression may appear inside the condition of a while loop and if it evaluates to non-zero, the body of the loop will be executed, and if it is zero, the body of the loop will not be executed.
The notation:
while (i = 0)
printf("Hello\n");
is always equivalent to:
i = 0;
There is very little justification for writing the loop at all.
People do write other expressions:
while (c = getchar())
...process EOF or a non-null character...
But that's usually a bug. It is more likely that you should be writing:
while ((c = getchar()) != EOF)
...process a character - possibly null...
or even:
while ((c = getchar()) != EOF && c != '\0')
...process a non-null character...
The first getchar() loop gets a warning from GCC; the latter two do not because of the the explicit test of the value from the assignment.
The people who write a condition like this:
while ((c = getchar()))
really annoy me. It avoids the warning from GCC, but it is not (IMNSHO) a good way of coding.
When you use an assignment operator such as
a=0;
You assign the value to 'a', and still return the number 0.
To test your question, I tried these lines of codes:
int a;
printf("%d", a=0);
and these lines displayed 0.
Then, I tested another set of codes:
int b;
printf("%d", b=15);
Here, the lines displayed 15.
So, if you do:
while(a=0)
{
printf("zero");
}
The (a=0) statement would return false, thus not displaying anything.
But if you do:
while(a=15)
{
printf("fifteen");
}
The "fifteen" will be displayed endlessly, because the statement (a=15) will return a non zero value, or 15, which is not false, not zero, thus it is true. :)
As cnicutar has told above the assignment also yields the value zero.
Some additional info:
It is a common coding mistake for people to omit an extra '=' whereby the comparison becomes an assignment.
An easy way to avoid this is to write the comparison as below, in which case even if a '=' is missed compiler will give an error
while(0 == i)
{
prinf("Hello");
}

Resources