Are inner-scopes ever used in C, or is this similar to something like a goto statement that isn't used too much in production code? The only thing I can think of that might use it is making something volatile temporarily, for example:
int main(void)
{
int a=1;
const int b=4;
printf("a=%d, b=%d\n", a, b);
{
int b=5;
printf("a=%d, b=%d\n", a, b);
}
}
But that seems like a pretty non-practical example. How would these be used in practice?
One case when blocks are required is defining local variables in a switch statement.
switch(foo())
{
case 0:
printf("no '{}' block generally required, except...\n");
break;
case 1:
{
int n = bar();
printf("%d\n", (n + 1) * n);
}
break;
//...
}
Without the {} block, the code would not compile because case 1: expects a statement right after, and declarations are not statements in C.
(Incidentally, the block is usually required in C++, too, though for an entirely different reason, because initialization of n would be skipped by other case labels.)
Are inner-scopes ever used in C, or is this similar to something like a goto statement that isn't used too much in production code?
Not so much by themselves, but inner scopes come up naturally all the time as the bodies of control statements such as loops and conditional statements. For example, a variable declared inside the body of a loop goes out of scope at the end of each iteration of the loop and is instantiated again during the next iteration.
we don't use them very often in production code. but this one very useful when you need your variable's scope very specific.
as far our use case, suppose you are coding in production code, and you want your some of variable's scope very specific . in this circumstances, we just use block {.....} to limit variable scope.
Related
Both kernel coding style and gnome's C style guide states that:
Do not unnecessarily use braces where a single statement will do.
if (condition)
action();
but at the same time it should be sometimes used, as in else branch of:
if (condition) {
do_this();
do_that();
} else {
otherwise();
}
Is there any technical or usability reasons to prefer it this way? Are there any objective reasons not to put the braces there everytime?
There are only stylistic and ease-of-editing-related reasons.
Whether you omit the brace or not, C compilers must act as if the braces were there (+ a pair around the whole iteration statement (if or if-else)).
6.8.4p3:
A selection statement is a block whose scope is a strict subset of the
scope of its enclosing block. Each associated substatement is also a
block whose scope is a strict subset of the scope of the selection
statement.
The existence of these implicit blocks can be nicely demonstrated with enums:
#include <stdio.h>
int main()
{
enum{ e=0};
printf("%d\n", (int)e);
if(1) printf("%d\n", (sizeof(enum{e=1}),(int)e));
if(sizeof(enum{e=2})) printf("%d\n", (int)e);
printf("%d\n", (int)e);
//prints 0 1 2 0
}
A similar rule also exists for iteration statements: 6.8.5p5.
These implicit blocks also mean that a compound literal defined inside an iteration or selection statement is limited to such an implicit block. That is why example http://port70.net/~nsz/c/c11/n1570.html#6.5.2.5p15 from the standard puts a compound literal in between a label an explicit goto instead of simply using a while statement, which would limit the scope of the literal, regardless of whether or not explicit braces were used.
While it may be tempting, don't ever do:
if (Ptr) Ptr = &(type){0}; //WRONG way to provide a default for Ptr
The above leads to UB (and actually nonworking wit gcc -O3) because of the scoping rules.
The correct way to do the above is either with:
type default_val = {0};
if (Ptr) Ptr = &default_val; //OK
or with:
Ptr = Ptr ? Ptr : &(type){0}; //OK
These implicit blocks are new in C99 and the inner ones (for selection statements (=ifs)) are well rationalized (C99RationaleV5.10.pdf, section 6.8) as aids in refactoring, preventing braces that are added from previously unbraced branches from changing meaning.
The outermost branch around the whole selection statements doesn't appear to be so well rationalized, unfortunately (more accurately, it's not rationalized at all). It appears copied from the rule for iterations statements, which appears to copy the C++ rules where for-loop-local variables are destructed at the very end of the whole for loop (as if the for loop were braced).
(Unfortunately, I think that for selection statement the outermost implicit {} does more harm than good as it prevents you from having macros that stack-allocate in just the scope of the caller but also need a check, because then you can only check such macros with ?: but not with if, which is weird.)
Well, there's one special case in which braces do need to be used: Suppose you have the following code:
if (a)
if (b)
f();
else g();
As it is indented, one could assume the else g(); statement belongs to the first if(a) statement, but C syntax rules say that it is interpreted as (now with braces):
if (a) {
if (b) {
f();
}
else {
g();
}
}
which actually means:
if (a) {
if (b) {
f();
}
else {
g();
}
}
in case you wanted the other possibility, then you must use braces. For example you can write it this way:
if (a) {
if (b)
f();
}
else
g();
which actually means:
if (a) {
if (b) {
f();
}
}
else {
g();
}
Note
As all elementary programming books recommend: If you are in doubt about operator precedence, then use parentheses; if you extend that to statements coding, if you are in doubt, use braces! :)
I hate those "if in doubt" guidelines with a passion. They engender laziness that pushes the cost onto the code reader.
Such guidelines lead to code that is more cluttered, slower to read, and therefore harder to debug.
If in doubt go and read the precedence table.
If still hesitating, write some test code to verify the interpretation.
Repeat this every time you code until precedence becomes second nature.
When you are sure you have a firm grasp of precedence, then and only then write the production code.
If you really can't manager that, then always break up your statements so that they contain no more than two levels of grouping parentheses in any one statement. If that means you have to make up lots of temporary variable names, that's a good thing.
I have a question regarding performance, specifically on how it looks affected when we have some nested functionn calls within loops and many variable definitions inside the deepest function call. For example, lets say we have the folliwing:
void fun2(){
for(int i = 0 i<FINITE_NUMBER; i++){
int a = 5*i;
int b = 6*i;
.
.
//A HUGE LIST
.
.
int zz = N*i;
/* some operations with a,b,..z */
//also, BESIDES THE SCOPE, what difference in performance would it make to declare a,b,...,zz outside of the for-loop?
}
}
void fun1(){
fun2();
}
int main(){
for(;;){
fun1();
}
}
My understanding is that every time that fun1() finishes, the scope of all the initialized variables within fun2() will be destroyed as, having to initialize them again in the next loop cycle. So, would it be better to get rid of the function nesting? **please note my question in the comment inside fun2() definition.
Also, will the compiler optimization -Os would notice this?
Thanks in advance, please let me know if Im not clear enough with my question!
Almost all compilers will be able to optimize the code (gcc, icc, clang) - the location of the declaration inside/outside the loop will not have impact. Better to keep the code logical and organized, and try to keep declaration and initialization close.
Thing that may help the compiler are
const (on variables) and
restrict (on pointers).
Block Scoped variables, indicating that values do not have to be persist between sections of the code.
They give the compiler extra information and flexibility to rearrange the code.
I know {} are used to separate entities such as functions, classes and conditional branching, but what other use would they have here?
#import <stdio.h>
int main(void) {
{{{
printf("main\n");
}}}
return 0;
}
EDIT:
I found that it may be useful primarily for information hiding, along with nested functions. From the answers below it would seem they can be used as a marker during debugging and be removed in the release, but that this should not be endorsed.
Enclosing a code in braces { } creates an Scope.
Creating an local scope can have number of reasons like:
Allows you to reuse a variable name in enclosing scope.
Define variables in middle of function.
Creating variables anywhere except at the start of an scope was not allowed in c89, but it is allowed since c99.
Online Example Code Sample:
#include<stdio.h>
int main()
{
int i = 10;
{
int i = 5;
printf("i is [%d]\n",i);
}
printf("i is [%d]\n",i);
return 0;
}
In your example code,
the extra { & } do not serve any purpose, they are just redundant code.
As #Martin suggests in comments, since enclosing code in {{{ & }}} is just similar to { & }, it might be used as an tag/pattern for easy search.
However, Personally, I would prefer adding appropriate comment to the code with an keyword which would show up in search rather than add such redundant code.
That syntax (three curly braces in a row) doesn't mean anything special in standard C. The author of such code might use it to indicate something about the code inside, like that it's just there for debugging.
you can introduce a new scope, which then allows you to introduce new variables.... which can be useful in C89. Not too normal though, but occasionally useful.
{
int x =2 ;
printf("%d", x);
{
int y = 7;
printf("%d", y);
}
}
Extra braces gives you scope as Als mentioned. This can be used in case of Smart Pointers effectively. e.g., consider the following code in C++ (MSVC compiler)
int i = 0;
i++;
//More code follows
...
{
CComBSTR bstr("Hello");
//use this bstr in some code
.....
}
After the end braces, bstr won't be available. Furthermore, since it has gone out of scope, therefore, the destructor will also get called automatically.
Is it possible to put the variable declarations in an external function? After reading from Wikipedia that:
an inline function is a function upon which the compiler has been requested to perform inline expansion. In other words, the programmer has requested that the compiler insert the complete body of the function in every place that the function is called, rather than generating code to call the function in the one place it is defined.
I hypothesized that the following might work. It did not take long for the compiler to slap my fingers :(
inline void declaration(){
int a;
}
int main(){
declaration();
a=2;
return 0;
}
This may not be how it is done but if you want a basic idea of how you can think about what happens when you inline a function.
Imagine the compiler turning your code into something like this, then you see why it will not work.
int main(){
{
int a;
}
a=2;
return 0;
}
The call to declaration() is replaced by the contents of the function including brackets, thus int a; is declared in an inner scope and is not visible in the main function.
No, this is not possible.
What is possible, is to use a preprocessor directive #define:
#define VARBLOCK int a, b, c; char ca, cb, cc;
int main()
{
VARBLOCK;
a = 2;
}
This would be a bad practice. Also these would still be variables only available in the scope of function where it were placed, without values being shared.
No - as far as I'm aware an inline function must behave semantically equivalent to a non-inline function; it doesn't affect what counts as legal code. It's just an optimization.
In particular, you could have a variable called a in both functions, but they'd be separate variables on the stack.
(Even if you could do this, I'd suggest it would be a very bad idea in terms of readability.)
inline functions are usually just a function containing no more than about 4 lines and you would want the compiler to do the optimization you where talking about since it would be faster to do what the function does, rather than adding extra code.
Inline expansion is used to eliminate the time overhead when a function is called. It is typically used for functions that execute frequently.
So there's nothing special with the inline function, rather than it might be handled differently by the compiler. They don't share their stack with any other function, which would be the only way for main to use a variable that is created in a different scope.
So my tip is; write your functions, and treat them as you usally should. Then when you are done, inline the short ones that you use a lot.
And if you really wanna create a variable in another function, allocate it on the heap in the function and return a pointer that you save and then set to 2 (your case). :) Just remember to free the memory!
You can do this, though:
#include <stdio.h>
int* GetMyIntAddress(void)
{
static int blah = 0;
return &blah;
}
int main(void)
{
printf("%d\n", *GetMyIntAddress());
*GetMyIntAddress() = 123;
printf("%d\n", *GetMyIntAddress());
return 0;
}
blah will be a global variable defined in the scope of the GetMyIntAddress() function.
If you add inline to the definition of GetMyIntAddress(), you are risking to get multiple independent instances of blah if the inline function is used in different modules (e.g. included from a shared header file).
Recently I had to modify a legacy code that was compiled with a very old version of GCC (somewhere around version 2.3). Within a function, variable had to be declared before being used. I believe this is done C89 standard. This limitation is later removed.
My question is: Back then, why did they enforce this ruling? Was there any concern that could jeopardise the integrity of the software?
Variables still have to be declared before being used -- and they've never had to be declared just at the top of a function.
The C89 requirement is that a block consists of an opening {, followed by zero or more declarations, followed by zero or more statements, followed by the closing }.
For example, this is legal C89 (and, without the void, even K&R C, going back to 1978 or earlier):
int foo(void) {
int outer = 10;
{
int inner = 20;
printf("outer = %d, inner = %d\n", outer, inner);
}
printf("outer = %d, inner is not visible\n", outer);
return 0;
}
C99 loosened this, allowing declarations and statements to be mixed within a block:
int foo(void) {
int x = 10;
printf("x = %d\n", x);
int y = 20;
printf("y = %d\n", y);
return 0;
}
As for the reason for the original restriction, I think it goes back to C's ancestor languages: B, BCPL, and even Algol. It probably did make the compiler's job a bit easier. (I was thinking that it would make parsing easier, but I don't think it does; it still has to be able to distinguish whether something is a declaration or a statement without knowing in advance from the context.)
It was mainly to make compilers easier to write. If all the declarations were at the top of the function, it would be easy for the compiler to parse all the locals and determine how much stack is needed.
Of course now, compilers are a lot more mature than they were 30 years ago. So it makes sense to get rid of this restriction as it's become a nuisance to programmers.