From: Grant Edwards on 29 Sep 2009 12:25 On 2009-09-28, Jon Kirwan <jonk(a)infinitefactors.org> wrote: > [First off, I want to make sure no one reading this is conflating the > idea of 'global' with 'static'. A global definition (in c) is always > a static definition. But not all static definitions are global.] The overloading of the 'static' keyword in the C language to modify lexical scope in one case and lifetime in another was a huge mistake IMO. -- Grant
From: Vladimir Vassilevsky on 29 Sep 2009 13:05 David Brown wrote: > This is comp.arch.embedded - a great many of the projects here do not > grow "large" because they are for small systems. The code is small > enough that is not a big problem to keep track of modules and their > interfaces, and that includes global variables. On the other hand, the > waste of runtime and code space caused by unnecessary accessor functions > /can/ be significant. Unfortunately, I've seen quite a few projects which were started as "small" and then overgrew into "large". It was too late to change the interfaces, so they ended up duplicating the entire modules by copy/paste and renaming the global variables by find/replace. "Code efficiency" is a very common excuse for sloppy practices. > To take another example, suppose you have a module that collects samples > from somewhere and puts it in an array dataSamples[]. Should that only > be accessible through a function "int GetDataSample(int n)" ? That > would make a summation function very slow. Should you have a > "CopyDataSamples(int * dest, int n)" to let users have a local copy? > Again, it's slow, and a waste of data space. Perhaps just "const int * > AccessDataSamples(void)" to return a pointer to the data - it's fast, > but loses the compile-time checking you get with simple clear access to > the raw global data. The notions of "Slow" and "Fast" are meaningless without respect to the particular application. A function either works or not works. If it works, I would do it in the most clear, portable and modular way. If there are the *real* constraints in size/speed, then I may have to resort to globals. Vladimir Vassilevsky DSP and Mixed Signal Design Consultant http://www.abvolt.com
From: Jon Kirwan on 29 Sep 2009 13:34 On Tue, 29 Sep 2009 16:25:36 +0000 (UTC), Grant Edwards wrote: >On 2009-09-28, Jon Kirwan <jonk(a)infinitefactors.org> wrote: > >> [First off, I want to make sure no one reading this is conflating the >> idea of 'global' with 'static'. A global definition (in c) is always >> a static definition. But not all static definitions are global.] > >The overloading of the 'static' keyword in the C language to >modify lexical scope in one case and lifetime in another was a >huge mistake IMO. hehe. Okay. I don't remember the history of it well, but I seem to recall that c derived the use within function bodies from FORTRAN. In other words, the use of 'static' for lifetime came from there. I think that use started at the very beginning. At least, it seems to me it did (and I've been using it since 1978.) However, the use of 'static' for scoping seems to me to have been a little later. (I really could be wrong, here.) And if so, it may have been used for reasons similar to those stroustrup gave for some choices made in c++ -- the desire to keep the keyword list changes to a minimum, in order to avoid breaking code to the extent possible. In other words, practical considerations. It is what it is. Jon
From: Dombo on 29 Sep 2009 13:45 John Devereux schreef: > Vladimir Vassilevsky <nospam(a)nowhere.com> writes: > >> David Brown wrote: >> >> >>> What I take issue with is when people get obsessive about globals >>> and think that it is somehow better to have functions called >>> "SetUartTimeout" and "GetUartTimeout", >> Yes it is better. >> >> * Perhaps it could be necessary to add flushing the UART before >> changing timeouts. You just have to modify one function. >> >> * What if there is a need to have more then one uart? How about >> accessing N uarts? >> >> * What if there is a need to access the timeouts from more then one thread? >> >> * What if there is a name conflict due to the use of the global objects? >> >>> doing nothing but accessing a static variable, instead of just using >>> a globally visible variable "uartTimeout". >> I do require all access to such variables via member functions. I like >> an overloaded function UART.Timeout() instead of separate Set.. and >> Get.. functions. > > How does that work, like: > > timeout = UART.Timeout(GET,UART1); > > ... > > UART.Timeout(SET,10000); Since Vladimir mentioned overloaded member functions I expect he means something like: class UART { public: void Timeout(int amount); // Set UART timeout int Timeout(); // Get UART timeout };
From: David Brown on 29 Sep 2009 15:03
Vladimir Vassilevsky wrote: > > > David Brown wrote: > > >> This is comp.arch.embedded - a great many of the projects here do not >> grow "large" because they are for small systems. The code is small >> enough that is not a big problem to keep track of modules and their >> interfaces, and that includes global variables. On the other hand, >> the waste of runtime and code space caused by unnecessary accessor >> functions /can/ be significant. > > Unfortunately, I've seen quite a few projects which were started as > "small" and then overgrew into "large". It was too late to change the > interfaces, so they ended up duplicating the entire modules by > copy/paste and renaming the global variables by find/replace. Projects that start small and then grow large is a bad sign in the first place. A common cause of this sort of problem is when people take "test" or "prototype" code and designs, and try to turn it into a finished product. It is always important to understand what you are aiming for in your code. Are you trying to write something specific for one application, or do you want it for general use? Are you trying to write something small and fast, or is that low importance for this particular piece of code? Does it need to be very portable? Does it need to be easily understood by others? You should not write code if you don't know /what/ you are targeting, and /why/ you are doing it in a particular way. Then you can (mostly!) avoid overgrowth issues. And of course, the use of global variables is a small issue in such cases - if you make a duplicate module with find/replace, you have the same issues with global functions or structures as with global variables. > "Code efficiency" is a very common excuse for sloppy practices. > "Premature optimisation is the root of all evil". However, too many abstractions is just as bad. Pick a happy medium, suited to the code in question. > >> To take another example, suppose you have a module that collects >> samples from somewhere and puts it in an array dataSamples[]. Should >> that only be accessible through a function "int GetDataSample(int n)" >> ? That would make a summation function very slow. Should you have a >> "CopyDataSamples(int * dest, int n)" to let users have a local copy? >> Again, it's slow, and a waste of data space. Perhaps just "const int >> * AccessDataSamples(void)" to return a pointer to the data - it's >> fast, but loses the compile-time checking you get with simple clear >> access to the raw global data. > > The notions of "Slow" and "Fast" are meaningless without respect to the > particular application. A function either works or not works. If it > works, I would do it in the most clear, portable and modular way. If > there are the *real* constraints in size/speed, then I may have to > resort to globals. > I use global variables when they are appropriate - the choice can often be because they make the code clearer (and perhaps also more portable and modular). Building fine oo interfaces and other abstractions /may/ make the code better (in the sense of making it clear, portable and modular), but it can also make it worse. If it is done as part of a consistent design pattern, it will help. If it is done simply because someone said that global variables were bad, it will make it worse. Of course, there is no doubt that code correctness is much more important than code speed, and also that clarity of code (which heavily influences its correctness, especially during later maintenance) is generally more important than raw speed. But given the choice of writing clear, efficient code or clear, inefficient code, I know which I choose. |