How are statements in C syntactically unique?

I don't know much 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; } 

all are syntactically equivalent. The statement is true; the line is printed; curly 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; } 

Through CodeGolf authority , I was fortunate that C is an opaque agnostic; the lexical analyzer breaks tokens into its component parts and skips spaces outside the lines.

(I mean, the whole reason for the semicolon is on each of the statements - so the parser can fill in the spaces \n , \t , and still know where each statement ends, right ??)

So, how can one unambiguously parse the previous bit of code (or maybe someone can come up with a better example of what I mean), if you ignore the spaces?

If C programmers want to write in space-dependent syntax, why do they write C, and why did they teach it everywhere, where C was taught that it is good to write lexically ambiguous (for me, the programmer, and the computer) such statements?

+5
source share
7 answers
 if (1 == 1) printf("one is one\n"); printf("is this inside the if statement??/who kn0WS\n"); 

The second printf() should never be executed inside an if .

The reason is that the previous line ends with a semicolon, which indicates the end of the executed if-block.

(I mean, the whole reason for a semicolon is an all-expression-thing so that the parser can cut out \ n, \ t literal spaces and still know where each statement ends, right?)

So, how can one unambiguously parse the previous bit of code (or maybe someone can come up with a better example of what I mean), if you ignore the spaces?

Analysis Example :

if (1 == 1) // , if - ( and ) - instructions (or block), skip all spaces

// no { found β†’ one operator, scan to ; (external quotes / comments)

printf("one is one\n"); // ; , end of if block

Without curly braces, only one statement refers to an if block.

But, as already mentioned, it’s a good habit to use braces. If you add an instruction later (for example, a quick temporary printf() ), it will always be inside the block.

Special occasion :

 int i = 0; while(i++ < 10); printf("%d", i); 

Here printf() will be executed only once. Note ; at the end of while() .

In the case of an empty instruction, it is better to use:

 while(i++ < 10) ; 

to make the intent understandable (or, alternatively, you can use the empty block {} ).

+5
source

In C, an if takes an exact expression after an expression of truth, regardless of the indent. This expression is usually indented for clarity, but C ignores indentation. In any case, there is no doubt about any of your examples.

What is ambiguous, in C and in many other languages, is "hanging out to others." For example, suppose you have a nested if with one else after the second. It can be grouped as:

 if (expr) if (expr) statement else statement 

Or it can be grouped as:

 if (expr) if (expr) statement else statement 

The only difference between the two is how they backtrack, which C ignores. In this case, ambiguity is allowed using the first interpretation, i.e. The else associated with the closest previous if . To achieve the second interpretation, braces are needed:

 if (expr) { if (expr) statement } else statement 

However, even in the first case, it is recommended to include curly braces, even if they are not required:

 if (expr) { if (expr) statement else statement } 
+5
source

tl; dr The only ambiguity is how difficult it is for a person to read. From a compiler point of view, the syntax is completely unambiguous.

There are only two (compiled and syntactically acceptable) possibilities after the if :

  • Brackets, as in

     if(x) { DoFoo(); } // or if(x) { DoFoo(); } 

    In this case, everything that is in {...} will be satisfied if the condition is met.

  • Lack of braces, as in

     if(x) DoFoo(); // or if(x) DoFoo(); 

    In this case, only the following statement is executed if the condition is met.

You are right that C is a blank agnostic. As a result, dropping braces can lead to some complex errors. For example, in this code, DoBar() will execute whether the condition is DoBar() :

 if(x) DoFoo(); DoBar(); 

Direct use of curly braces can also easily lead to invalid code. For example, it looks reliable (at first glance) from a human point of view, but it is not:

 if(x) DoFoo(); DoBar(); else DoBaz(); 

None of the examples you cited is ambiguous from the point of view of the compiler, but versions without binding are confused from a human point of view. Leaving braces often leads to hard-to-reach mistakes.

+3
source

Without curly braces, this is simply the next statement after if. Space does not matter

This is good practice and makes life easier when using braces. Good print. Then the code is easy to read and does not lead to errors when people add / remove instructions after if

+2
source

Reading is the only ambiguity in the instruction:

 if (1 == 1) printf("one is one\n"); printf("is this inside the if statement??/who kn0WS\n"); 

The only time that the first statement should follow after the if(...) if it evaluates to TRUE.

Braces, {...} help eliminate the ambiguities of readability,

 if (1 == 1) { printf("one is one\n"); } printf("is this inside the if statement??/who kn0WS\n"); 

but the syntax rules are the same.

Opinions change, but I always prefer to use curly braces. Do not use them in the order of writing time code. But along the way, you just know that someone will come and add another expression under the first and expect that it will be executed.

+2
source

In the general case, in a statement or in a single-instruction loop, curly braces are options; instead, if you have two or more instructions, you should add them. For instance:

 for(i = 0; i < 2; i++) for(j = 0; j < 4; j++) If(...) printf(..); else printf(..); 

It is equivalent to:

 for(i = 0; i < 2; i++) { for(j = 0; j < 4; j++) { If(...) { printf(..); } else { printf(..); } } } 

As you can see, this has more to do with code indentation. Personally, I do not use curly braces if I have one instruction, as this will make your code shorter and cleaner.

+2
source

Another reason for using curly braces is that a simple typo can bite you badly:

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

+2
source

Source: https://habr.com/ru/post/1240769/


All Articles