tags:

views:

1140

answers:

17

In the C programming language, it is my understanding that variables can only be defined at the beginning of a code block, and the variable will have the scope of the block it was declared in. With that in mind, I was wondering whether it is considered bad practice to artificially create a new scope as in this example:

void foo()
{
     ... Do some stuff ...

     if(TRUE)
     {
         char a;
         int b;

         ... Do some more stuff ...
     }

     ... Do even more stuff ...
 }

Assuming TRUE is set to 1 in a macro definition, would this code be considered 'good code' or does it make seasoned programmers cringe at the very thought of it?

Thanks for your input!

EDIT: In response to some of the answers, the code I am working with needs to work with some pretty ancient legacy systems. While it would be nice to operate on an assumption of C99, we really can't guarantee that they will have it.

+6  A: 

You probably want to create a new function for that scope.
If it truly needs to have it's own scope, it's probably a separate logical function anyway.

Lars Mæhlum
Not necessarily. I've often encountered a need for some highly local variable (with a nice mnemonic name) to hold some intermediate value for only a few lines. By using a nested scope, you make clear its intended (restricted) use.
joel.neely
+2  A: 

I wouldn't call myself seasoned, but I'm kind of cringing.

My issue with it is that the if statement would lead someone to believe that something is actually being evaluated...but at runtime, the macro is either true or false there's no change of it being something else. You should either include the code or not.

If what you mean to do is something like #ifdef DEBUG then you should do that to indicate to the reader that this is debug code...

Jason Punyon
The macro is evaluated at compile time, not run time.
Jonathan Leffler
+1  A: 

I don't think you need the if(true) portion.

Just the { } are required to scope the variables.

VBNight
+1  A: 

My answer is as follows:

This makes seasoned programmers cringe at the very thought of it.

+5  A: 

Since you can just make the scope block without the if, that's a better idea.

void foo() {
     ... Do some stuff ...
     {
         char a;
         int b;
         ... Do some more stuff ...
     }
     ... Do even more stuff ...
}
chaos
+14  A: 

As far as I know you can create a scope without if.

Use just the braces like this:

{
    int x;

}

And I recommend against

if (TRUE)

since it hinders readibility.

Richard J. Terrell
especially if you #define TRUE 0
Pete Kirkham
+39  A: 

You don't even need an if statement. You can create blocks with {}

That should probably be a separate function however.

Example here:

#include <stdio.h>

int
main(int argc, char **argv) {
    int i = 0;
    {
        int i = 10;
        printf("%d\n", i);
    }
    printf("%d\n", i);
}
Phil
Is this ever used in production code? My thought is that I want to have access to all the variables in the existing function, but a few new variables apply to only a small section. A function would mean I would have to pass a whole bunch of variables, and adding the variables to the main...
Tim
... function would clutter the function's existing variables
Tim
my company uses this extensively. I used to be really against it when I started working here, but now I like it. I still don't like the way we use it though, which is generally to break up chunks of 1000 line functions that should be their own function...
rmeador
I like doing this hiding scopes especially for temp variables. { char * tmp=something, what allocates memory; do something with tmp; free(tmp); }
bothie
Scoping is a nice thing, I also tend to use it. Shadowing variables by using the same name .. not so much ;)
ypnos
In C++ (rather than C), this is used extensively. One prevalent example would be a lock class for a mutex that locks the mutex in it's constructor and unlocks it in it's destructor. Creating a lock variable on the stack then protects a critical section with the same scope as the block.
+3  A: 

You can remove the

if(TRUE)

and just leave the braces, which by themselves define a new syntactic block - a compound statement.

This is definitely cleaner than the false if you had before, but you might still like to ask yourself why you want to create a new block - would it be better to define a subroutine?

Mark Pim
+3  A: 

First of all, a new block doesn't need to be an if block. It could simply be a section of code surrounded by braces, like this:

void foo() {
 ... Do some stuff ...

 {
     char a;
     int b;

     ... Do some more stuff ...
 }

 ... Do even more stuff ...
}

Second of all, in any modern C compiler which complies to the C standard (I think C99), you can declare variables anywhere in the block, so you don't need to create a new block at all.

Avi
+1  A: 

Leaving the door open for some creative folks:

#define TRUE 0
#define FALSE 1

Just use the braces to declare the scope.

Anonymous
A: 

C99 allows you to declare variables almost anywhere. However, refrain from doing it without a very good reason. Try first to split your function into smaller (possibly inline) functions.

The only place where such a thing might make sense is when you have a variable that is initialized in the middle of your function, e.g. similar to creating an object in C++.

Eduard - Gabriel Munteanu
I'm not sure why you say to refrain from doing so. If I need a simple int or char, it seems cleaner to declare it close to the code that's going to use it, rather than sending it to the top of the function. What am I giving up by doing this?
rtperson
Declaring variables at the point of first use is considered good practice in C++. Why not in C99?
David Thornley
@David Thornley: C usually allows the programmer to write very long functions, more likely than C++ due to lack of OOP language features. Having many variables at the start of a function is a good sign that it's too long. Practice can be a habit. But declaring just before first use can be legitimate
Eduard - Gabriel Munteanu
A: 

I think you're working with some outdated assumptions. I've been coding straight C using GCC for a few months now, and you don't need to declare variables at the beginning of a block, even though the Second edition of K&R says you have to. You can declare your variable anywhere, like like this not-very-useful example:

char* palstring;
palstring = malloc(LARGEST_STRING);
memset(palstring, 0, sizeof palstring);
fgets(palstring, LARGEST_STRING, fin);

char* cur = palstring;
char letter;
letter = *cur;

So there's no need to do what you're suggesting. The language has moved on.

Another good addition to the C language is Variable Length Arrays, which allow you to pass an array to a function along with its size. In the old days, all you could do was pass in a pointer.

rtperson
Careful gcc's variable length arrays aren't C99 standard
Martin Beckett
Ah, good to know. Thank you. I'm mainly using it for goofing around on my own, so I'm not too worried, but if I ever have to use it professionally, I'll owe you a beer. :)
rtperson
+3  A: 

As so many answers already said, you don't need the "if" stuff. Just create the bare block. But i want to get at another point. In C, you can create variable declarations anywhere in a block, not only at the start. In C89, you had that restriction. Starting with C99 (that's 10 years now), you don't have that restriction anymore, although some compilers will moan anyway. GCC won't, though, if you tell it to use the most "recent" C Standard with the -std=c99 option.

Because there are still compilers in existence that moan by default, i would not prefer mixing declarations and code though. I would keep putting declarations at the start of blocks for compatibility reasons.

Johannes Schaub - litb
Yeah, I think this bad practice in C. If you compile with -Wall -ansi -pedantic, you will get warnings. My rule of thumb is if it doesn't pass those flags clean, it's generally wrong.
BobbyShaftoe
BobbyShaftoe. well, that's a valid point. but i don't think it's bad practice. i avoid using -Werror precisely because sometimes the compiler may warn wrongly. that then, if it warns for "... { ... } ..." which is properly commented, is a false positive for me.
Johannes Schaub - litb
+3  A: 

Note that in C99 it is allowed to declare local variables in the middle of blocks.

C99 is the version of the C standard from the year 1999; most modern C compilers support it.

starblue
A: 

Assuming that you use an old compiler (like I do, it's for old hardware), that you skip the if(TRUE) like others have suggested, and that you have a really HUGE function (witch you should not have in the first place), then I think it's sort of ok. I have done it but it did not feel good...

c0m4
A: 

Apparently I'm in the minority, but I find "just braces" much harder to read because it deviates from the usual pattern. On the (admittedly infrequent) occasions where I want a scoped block without defining another function, I prefer to include the "if", but without any macros and with a comment to explain why:

if( 1 ) // just to establish scope
{
   // do stuff here
}
Eric
+1  A: 

Just define your variables at the beginning of the block or use another function. Adding an artificial scope with empty {}s or any of the alternatives is not good practice.

BobbyShaftoe