Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

A block is a list of statements to be executed. Examples of where blocks come up in C are after a while statement and in if statements

while( boolean expression)
    statement OR block

if (boolean expression)
    statement OR block

C also allows a block to be nested in a block. I can use this to reuse variable names, suppose I really like 'x'

int x = 0;
while (x < 10)
{
    {
        int x = 5;
        printf("%d",x)
    }
    x = x+1;
}

will print the number 5 ten times. I guess I could see situations where keeping the number of variable names low is desirable. Perhaps in macro expansion. However, I cannot see any hard reason to need this feature. Can anyone help me understand uses of this feature by supplying some idioms where it is used.

share|improve this question
1  
Honestly, I am just trying to understand the C syntax, and am curious. –  Jonathan Gallagher Dec 22 '13 at 20:00
    
The spirit of C is to trust the programmer. The programmer has the power at his disposal to make something great... or make something terrible. Personally, I don't like overloaded variable names but another programmer may. At the end of the day if we're accomplishing what we're supposed to with minimum bugs... why should we argue? –  Fiddling Bits Dec 22 '13 at 20:54
1  
That is the feeling I get from C. I am all for syntax that supports different styles of coding (well as long as the semantics of the language is okay). It's just that ... I saw this, and my immediate response was, I could apply a source-to-source transformation renaming all of the variables in a block with fresh names, and flatten out the block completely. Anytime I think I could get rid of something, I assume there is something I have missed. –  Jonathan Gallagher Dec 23 '13 at 0:44
    
Funny timing, as a non-C programmer I stumbled across this syntax today in C code and was curious what it was for. I am glad you asked. –  Brandon Dec 24 '13 at 16:56
add comment

7 Answers 7

up vote 8 down vote accepted

The idea isn't to keep the number of variable names low or otherwise encourage reuse of names, but rather to limit the scope of variables. If you have:

int x = 0;
//...
{
    int y = 3;
    //...
}
//...

then the scope of y is limited to the block, which means that you can forget about it either before or after the block. You see this used most often in connection with loops and conditionals. You also see it more often in C-like languages such as C++, where a variable going out of scope causes it's destruction.

share|improve this answer
    
I think block naturally occur with conditionals, loops, and function bodies. What I am curious about is that in C, I can place a block anywhere. Your second comment about C++ is interesting -- that leaving a scope causes destruction. Is this referring only to garbage collection, or is the following another use: could I take a function body, which has distinct "sections" and use blocks to control the memory footprint by triggering destruction of the variable space? –  Jonathan Gallagher Dec 23 '13 at 0:49
1  
As far as I'm aware, C will preallocate all the memory for all variables in the function. Having them exit scope part way through a function will have no performance benefits in C. Similarly having variables enter scope "only sometimes" will not change the memory footprint during any call to the function –  Gankro Dec 23 '13 at 3:39
add comment

Because in ye olden days of C new variables could only be declared in a new block.

This way programmers could introduce new variables in the middle of a function without leaking it and minimizing stack use.

With todays optimizers it is useless and a sign that you need to consider extracting the block in its own function.

In a switch statement, it is useful to enclose the cases in their own blocks to avoid double declaration.

In C++ it is very useful for example for RAII lock guards and ensuring the destructors run the release lock when execution goes out of scope and still doing other stuff outside of the critical section.

share|improve this answer
1  
+1 for the RAII lock guards. That being said, couldn't this same concept also be useful for large-ish stack buffer deallocation within parts of a routine? I've never done it, but sounds like something that could definitely occur in some embedded code... –  J Trana Dec 23 '13 at 2:44
add comment

I wouldn't look at it as "arbitrary" blocks. It's not a feature meant so much for developer use, but the way C uses blocks allows the same block construct to be used in a number of places with the same semantics. A block (in C) is a new scope, and variables that leave it are eliminated. This is uniform regardless of how the block is used.

In other languages, this is not the case. This has the advantage of allowing less abuse like you show, but the disadvantage that blocks behave differently depending on what context they are in.

I've rarely seen standalone blocks used in C or C++ - often when there's a large structure or an object that represents a connection or something that you want to force destruction of. Usually this is a hint that your function is doing too many things and/or is too long.

share|improve this answer
1  
Unfortunately I regularly see stand alone blocks - in almost all cases because the function is doing to much and/or is too long. –  mattnz Dec 22 '13 at 20:31
    
I also regularly see and write standalone blocks in C++ but solely to force destruction of wrappers around locks and other shared resources. –  J Trana Dec 23 '13 at 2:39
add comment

You have to realize, programming principles that seem obvious now were not always so. C best practices greatly depends on how old your examples are. When C was first introduced, breaking your code into small functions was considered too inefficient. Dennis Ritchie basically lied and said function calls were really efficient in C (they weren't at the time), which was what got people started using them more, although C programmers somehow never really got completely past a culture of premature optimization.

It is a good programming practice even today to limit the scope of your variables as small as possible. Nowadays, we usually do that by creating a new function, but if functions are considered expensive, introducing a new block is a logical way to limit your scope without the overhead of a function call.

However, I started programming in C over 20 years ago, back when you had to declare all your variables at the top of a scope, and I don't recall variable shadowing like that ever being considered good style. Redeclaring in two blocks one after another like in a switch statement, yes, but not shadowing. Maybe if the variable was already used and the specific name was highly idiomatic for the API you're calling, like dest and src in strcpy, for example.

share|improve this answer
add comment

Arbitrary blocks are useful to introduce intermediary variables that are only used in special cases of a computation.

This is a common pattern in scientific computing, where numeric procedures typically:

  1. rely on a lot of parameters or intermediary quantities;
  2. have to deal with a lot of special cases.

Because of the second point, it is useful to introduce temporary variables of limited scope, which is achieved wether by using an arbitrary block or by introducing an auxiliary function.

While introducing an auxiliary function may look like a no brainer or a best practice to blindly follow, there is actually little benefits to do so in this particular situation.

Because there is a lot of parameters and intermediary quantities, we want to introduce a structure to pass these to the auxilary function.

But, since we want to be consequent with our practices, we will not introduce only one auxiliary function but several. So, wether we introduce ad-hoc structures conveying parameters for each function, which introduce a lot of code-overhead to move parameters back and forth, or we introduce a one will rule them all worksheet structure, which contains all our variables but looks like a grabpack of bits without consistence, where at any time only the half of parameters have an interesting meaning.

Therefore these auxiliary structures are typically cumbersome and using them means choosing between code-bloat or introduce an abstraction whose scope is too broad and weaken the meaning of the program, instead of stregthen it.

Introducing auxiliary functions could ease unit testing of the program by introducing a finer test granularity but combining unit testing for not that low-level procedures and regression testing in the form of comparisons (with numdiff) of numeric traces of the procedures does an equally good job.

share|improve this answer
add comment

In general, the reuse of variable names in this manner causes too much confusion to future readers of your code. It's better to simply name the inside variable something else. In fact, the C# language specifically disallows the use of variables in this manner.

I could see how the use of nested blocks in macro expansions would be useful for preventing variable naming collisions.

share|improve this answer
add comment

It's for scoping things that normally don't have scope at that level. This is extremely rare, and in general refactoring is a better choice, but I have run across it once or twice in the past in switch statements:

switch(foo) {
   case 1:
      {
         // bar
      }
   case 2:
   case 3:
      // baz
      break;
   case 4:
   case 5:
      // bang
      break;
}

When you consider maintenance, refactoring these should be balanced with having all the implementations in a row, as long as each is only a couple lines long. It can be easier to have them all together, rather than a list of function names.

In my case, if I recall correctly, most of the cases were slight variations of the same code - except that one of them was identical to another, just with extra preprocessing. A switch ended up being the simplest form for the code to take, and the extra scope allowed use of extra local variables that it and further cases didn't have to worry about (such as variable names accidentally overlapping with one defined before the switch but used later).

Note that the switch statement is simply the use of it that I've run across. I'm sure it can apply elsewhere as well, but I don't recall seeing them used effectively that way.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.