This Time Self-Hosted
dark mode light mode Search

Varying the scope

I think most of the code I’ve ever seen in free software tends to follow the rule of declaring the variables for a function at the top before any line of actual code. While it’s true that it looks cleaner and that it makes it easier to find where a variable is declared and thus its type, it makes it quite more difficult to find where the variable is actually used.

In particular, considering xine’s architecture featuring humongous and convoluted functions, a variable might be declared, but not initialised, 200 lines before its first initialisation, and thus its actual first use. This is pretty bad because the variable is available for 200 lines with a non initialised value, which might be quite random.

It’s not just that though, as one problem with declaring all the variables at the top and then filling them in later makes it impossible to grep to check if the code ever puts the value returned by strlen() directly on an integer variable (which would be quite bad by its own), and disallows you from marking something constant rather than a variable.

I really like marking everything I can as constant, it makes it possible for me to assume that the data assigned to that particular name will always be there. I’ll gladly use ten different constants rather than reusing the same variable. If I have to, I put them in their own little scope till I use them and then get rid of them exiting the scope.

But there are more things that I find better to do by mixing declarations and code instead of keeping them separated. Easy enough, checking prerequisites: if a function needs to check whethere the parameters it has been given make any sense, and then start allocating a lot of objects, in variables that will never assume any other value than the pointer just allocated, I find it easier to declare them constant, checking the prerequisite before declaring them.

Quite often in xine-lib I can find strings being duplicated in the declaration of a variable, but then the prerequisites are checked and the function returns without freeing the allocated area. And marking those pointers constant often makes sure that you’re not going to change the pointer, calling free on a pointer different than the one allocated (yeah I’ve seen that today whle changing some functions around).

Reducing the scope, and thus the visibility, of variables and constants should also make the life of the compiler easier, as you’re suggesting when the variable is needed and when it ś not needed anymore. You help the compiler, and the compiler helps you not to use a variable once it isn’t valid anymore, by not allowing you to use it.

I find C99 for loops also quite interesting for the same reason, instead of having to keep the i index around for all the function, you’re using it and discarding it right away, makes it explicit for both you and the compiler what’s going on with i.

So yeah most likely most people wouldn’t like to work with me on a project I use my style on, but I’m good at adapting so if I have to hack at a software where the separated declarations and code style is used, I can easily change to apply that, but I might end up doing more scopes than the average 😉

P.S.: I got a tripod for my camera, hopefully the next set of photos I make to the flowers will be less blurred 😉

Comments 7
  1. I would guess that this is the C tradition and lots of free software code is written in C.In C++ it has always been recommended to declare a variable as late as possible because constructors can take significant amount of time to run and one should not invoke them if they are not needed.Modern languages as Java, where most variables are pointers, do not impose the same pressure to do late declarations as C++ does.

  2. I once read that C has to have them declared at the start. Obviously this is not the case now, at least with gcc, but was it ever the case? I do it through force of habit and because I have believed that it is the right thing to do. Am I simply following prehistoric rules that really have no relevance anymore?

  3. Christoph, I suppose the fact that I did learn to program on real-world languages (that is, not GW-BASIC or QBASIC) with C++ bears quite a part in my using more C99 syntax (which is basically C++’s basic syntax ported to C, booleans, for loops and similar).I sincerely never tried implementing or hacking at an interpreted language (at least partially) so I sincerely don’t know how variable scope applies to stuff like Java and similar.James, I think it was ANSI or K&R C which requires *not* to mix declarations and code, as far as I can see, C89 and for sure C99 allow to mix those. GCC 2.95 doesn’t support the mix, not by default at least, and that drives me crazy quite a bit when I’m doing job stuff because the embedded board I work on still uses GCC 2.95 as compiler. There is where I use a _lot_ of scope blocks.In the case of xine there is no problem as building it with GCC 2.95 is quite silly, and FFmpeg already requires a C99-compliant compiler. My own projects tend to use pure C99 directly (-mstd=c99 on the CFLAGS), as I like having booleans around and C99 for loops.

  4. Declaring global variables at the start of the program used to be the way programming was thought to students before object oriented programming took of. The same for declaring variables inside functions btw.I think learning it that way is still beneficial as most beginning programmers I’ve seen have great difficulty writing a clear piece of code that others understand. Declaring variables at the start then forces you to think about the structure.Off course C++ (as well as C99) have long discussions on how to efficiently declare variables, etc. but that were typically not the languages used to learn people how to program.For example my official courses used to be Pascal (and Modula-2), in which clearly you don’t worry about the kind of optimizations you look at in C/C++. Moreover as far as I remember you had to be careful as variables from for-loops kept their value outside of the for-loops. So you develop different approaches then used in C/C++

  5. Both approaches have pros and cons.I like have small function and variables declared at the top of them. This way the code is usually cleaner.Having large functions is already wrong, mixing variable declarations and code usually lead to unmaintainable mess.

  6. Diego, I’m pretty sure C89 does not allow the mixing, and only C99 does. In Mesa, we had to revert to C89 for stupid Microsoft compilers, and part of that was no mixed variable declarations.

  7. Uh then it might be only the Gnu89 variant to support it.Although I wouldn’t count on Microsoft’s compiler to get the language spec right anyway, Visual C++ up to version 6 at least defaulted to C89-like for *in C++ code*.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.