Curly brace scandol!

Hi there I'm Logan a beginner in C++, I would like to ask what are the working rules for curly braces.

I've got an example below:


int main() {
int score;
cout << "type score";
cin >> score;
switch (score) {
case 3:
cout << endl << "1 ready for your course.";
break;

case 4:
cout << endl << "2 ready for your course.";
break;

case 5:
cout << endl << "3 ready for your course";
break;

default:
cout << endl << "you suck " << endl;
}
return 0;
}
What confuses the hell out of me, is this will only run if the curly braces are placed like that and I cannot understand why there is two extra ones, number two and number three I, do not understand why they are needed, and for that matter how do we learn the proper use of them. When not to over use them and under use them. Where can I learn this?

Because here we got a second brace not closing but also opening and then a third closing and further down another closing why? What is the rules, can anyone explain in easy terms?

















Braces are scopes, with different sintaxes, meanings and such. A 'case' is allowed inside a switch scope, while a 'continue' is allowed inside a loop, etc. Also, variables declared inside a specific scope are deallocated when they go out of the scope (basic types and objects, not pointers). Braces and scopes are far more complex, but basically, that's it.
Last edited on
Every opening brace has a closing brace.
The example code in the opening post can be considered in its simplest form like this
 
int main() {  }
That's one matched pair of opening/closing braces.

In addition, there is the control structure,
 
    switch (score) { }
That's another pair of opening closing braces.

Now in this case, one is nested within the other, like this:
1
2
3
4
5
int main() {  

    switch (score) { }

} 

Though the rules are simple, keeping track of them can be a challenge. The first way to do so is to make proper use of indentation, so that the relationship between open/close is easily visible.

An additional tool is to use an editor or IDE which visually highlights matching pairs of braces (and brackets/parentheses).
For example Notepad++ is one such editor for the Windows environment

https://notepad-plus-plus.org/
Chervil wrote:
For example Notepad++ is one such editor for the Windows environment

Some people hate against Notepad++. :P
That's fair enough - let people choose as they wish.
Why the need for the curly after switch(score0, and the one closing before return 0?




Lazpeng, I think you answered why they are variables, I wondered about why a constant was even needed, until you mentioned that once the scope is ended the variable are being de-allocated. So that makes sense that you need to declare a value if you mean to keep it true all the way through the program.
@logana the curly braces specify the start and the end of the switch's body, which has different rules and syntax than it's parent, the 'main' function. Stuff like 'case', 'break', etc are allowed inside a switch statement, but aren't inside a function body, so you need to specify explicity where the switch starts and where it ends, using the braces
Last edited on
As you've probably figured out, braces, parentheses, and brackets can be nested. In source code that actually gets compiled (i.e., code that's not a string literal, character literal, or a comment) they must always match with another character of the same type.

Braces are a required component of most control structures, like switch. The braces tell you where the switch statement ends, and introduce a new lexical scope.
http://www.cplusplus.com/doc/tutorial/namespaces/

lazpeng wrote:
Also, variables declared inside a specific scope are deallocated when they go out of the scope (basic types and objects, not pointers)
This isn't correct. Only objects with automatic storage duration follow this rule, even pointers.

The switch is entirely consistent with the rest of C++'s syntax, except that case labels (and a single default) is allowed within it. A helpful (although not strictly correct) way to think about switch is as an jump table.

Control structures can be nested inside a switch arbitrarily, irrespective of the position of any label.
Any article on Duff's device will help illustrate the versatility of switch. You can do weird, inadvisable things with it:
https://en.wikipedia.org/wiki/Duff's_device
For another example, see this thread:
http://www.cplusplus.com/forum/lounge/201309/
This isn't correct. Only objects with automatic storage duration follow this rule, even pointers.

Thanks, I forgot to mention this. But, about pointers, I was referring to memory leaks. If you dynamically allocate memory on the heap using raw pointers and don't free it, the variable holding the address will be deallocated (if with ASD) but the data on the heap will leak, right?
braces are the C/C++ equivalent to BEGIN/END in other languages.

Only switch and try statements dictate braces ( i think), this is because switch() contains multiple statements, and try catch reflects standard exception processing that will unwind a stack (the same thing as closing a scope)

All other statements (i think) affect only the statement that follows it.
eg;
1
2
while (true)
    DoSomething();


if you want to execute more than one statement you need to use braces to wrap them up into a single "compound" statement code
1
2
3
4
5
while (true)
{
    DoSomething();
    DoSomethingElse();
}


Braces are also used heavily in declarations, classes, functions, structs, enums etc...

http://www.cplusplus.com/doc/tutorial/control/

@mBozzi, lazpeng is correct when saying
variables declared inside a specific scope are deallocated when they go out of the scope
the data you describe is not declared, it is allocated at run time. The pointer is declared, so is deallocated. I always consider "declared" to mean "declared to the compiler so it can manage its lifetime".

Also switch statements are not consistent with other C/C++ statements, they are a hang up from earlier languages like BCPL. this is why the options are declared with goto labels case label: instead of blocks, its also why break is required for each option, it's a standin for goto endofswitch

Last edited on
lazpeng wrote:
If you dynamically allocate memory on the heap using raw pointers and don't free it, the variable holding the address will be deallocated (if with ASD) but the data on the heap will leak, right?

Yes -- your resource (memory in this case) has dynamic storage duration, and has nothing to do with your pointer to it. If that pointer has automatic storage duration than it will be destroyed when it leaves scope but the resource it points to will remain until it's released.

Jaybob66 wrote:
@mbozzi, lazpeng is correct when saying
variables declared inside a specific scope are deallocated when they go out of the scope

No, you're mistaken.
1
2
3
void foo() { 
  static int x; 
}
An object's storage class has nothing to do with where it was declared.

Specifically, a "declaration" doesn't imply any particular storage class or linkage specifiers; it's possible to declare an object with a non-automatic storage class, as I've done above.

Break isn't required at the end of each case statement either (follow the links I posted). But switch-case is usually superior to goto because it will generate dispatch code for you; this is why case labeled statements are used instead of ordinary labeled statements.

But by "consistent" I meant that it is compatible with the rest of C++'s control structures. Given that case may appear nowhere else in the language, I admittedly made a terrible choice of wording.

I've always found it useful to think about switch-case in terms of the equivalent assembler code. It doesn't have much of a place in many C++ programs.
Last edited on
the static example is a fine example :)

and indeed break is not required, but the switch statement can be pretty useless without it.
case labels are goto labels, you can goto them :) I guess that comes from the jump table days, and is part and parcel of why only consts can be used.

case labels are goto labels, you can goto them


You can't goto case-labeled statements. You can only goto plain labeled-statements. :)
Edit: Strictly speaking, you don't goto labels, you goto labeled statements. I have to make that distinction because that struck-out bit is technically wrong. This is because you can goto a case-labeled statement if that statement is also a labeled statement...

Colloquially, you can't "goto" case-labels, just ordinary labels.

Case-labeled statement: case some_constexpr: some_statement;
"Ordinary" labeled-statement: some_label: some_statement;
labeled and case-labeled statement: some_label: case some_constexpr: statement;

1
2
3
4
5
  switch(i) {
  case 0: label1: std::cout << "Hello World!" << "\n";
    goto 0;      // error
    goto label1; // okay
  }


Check out these links I for an example of how to (ab)use switch without break;
https://en.wikipedia.org/wiki/Duff's_device
http://www.cplusplus.com/forum/lounge/201309/
Last edited on
Topic archived. No new replies allowed.