C: Re-declare vars in loop
John Kauffman
Posts: 653
I saw some code with one line for a var that declares and assigns. It is located in a loop.
Code works fine but two things do not make sense to me.
1 - I would have thought it better to declare vars once before the loop and only re-assign each loop. Why re-declare every loop?
2 - Why not an error for "redeclaration of 'myVar' with no linkage" like normal when declare 2nd var with a name already used?
- Thanks.
/* program: Re-declare vars in every loop? */
#include "simpletools.h"
int main(){
while(1){
int button = input(3); int otherButton = input(4);
print("%c button = %d, otherButton = %d \n", HOME, button, otherButton);
pause(200);
}
}
Code works fine but two things do not make sense to me.
1 - I would have thought it better to declare vars once before the loop and only re-assign each loop. Why re-declare every loop?
2 - Why not an error for "redeclaration of 'myVar' with no linkage" like normal when declare 2nd var with a name already used?
- Thanks.
/* program: Re-declare vars in every loop? */
#include "simpletools.h"
int main(){
while(1){
int button = input(3); int otherButton = input(4);
print("%c button = %d, otherButton = %d \n", HOME, button, otherButton);
pause(200);
}
}
Comments
More to the point the variables "button" and "other Button" there are defined inside curly braces "{...}". Which just happens to be part of a loop construct in this case.
That means they cannot be used outside those curly braces. The braces demark a "block" and those variables, being defined inside it have "block scope". It the same idea as how variables local to a function are not available outside that function. They are in the functions block scope.
You can even create block scopes without a function or control statement,like so: Don't think of this as redclaring the variable on every go around the loop. It is only "created" once and is local to the loop as it executes.
(short post due to mob. device -Tor)
Oops, well spotted. Now fixed.
Further to the story: Why would one want to put declarations in a block scope like that?
It's a message from the author to the reader of the code that he really means these variables to only be used within that part of the code.
It's a way of keeping things neat and tidy. Declare things as close to where they are used as possible, don't clutter up the code.
Otherwise it has no impact on performance at all.
On the down side it can lead to confusion. If you are using the same name for variables in inner scopes and outer scopes and all over then the reader get's lost.
I usually only do it for loop counters and such. Like so: That "i" is of no use except in the scope of the loop so no point in cluttering up any local variable declarations with it.
And what would make you think that? If you're worried about performance, fear not. Variable allocation is done during compilation, not run time. Most likely, the generated assembly is going to be identical in your simple example, no matter where the variable is declared.
In fact, in languages that are interpreted rather than compiled it may well be true and cause a performance issues.
Consider this in JavaScript as an example: In that code every time around the loop "x" becomes a totally different type of variable: a number, a string, and array, an object.
Now, JS can perform almost as well a compiled C code, but this kind of redeclaration to different types totally defeats the run time optimizer and things slow down my orders of magnitude.
I'm not sure what I mean by my example.
It seems clear though that if you come to any programming language for the first time you may well assume things about what it says that fit your preconceived ideas about how programming languages work rather than what the thing in front of you actually does.
As a trivial example, the *** backwards operators in Spin still catch me out as an old C/Java/JavaScript/Pascal programmer.
Think of it as learning the spirit of the language instead if the letter of the language.
If I recall, java is filled with a lot of little gotchas that look innocent when you write the code but the runtime goes througn herculean effort to make it happen. Languages with immutable data types generally have little tricks to make it more efficient to work with those types. What looks good in the source code may or may not turn out so good at run time.
Another one is 'const', which of course also prohibits the programmer for assigning to the variable.. but that's not the real reason. The real reason is to tell the C optimiser that it's safe to optimise something that could not otherwise be optimised. Consider: This tells the compiler that the function that the programmer may call will never do anything with what the 'in' pointer points to, and indeed not the pointer itself. No side effects, calling the function will not affect 'in', optimise as hard as possible. Then it tells the compiler that what the 'out' pointer points to will presumably be updated. So be careful about that one. But at least the function will not fiddle with the pointer itself (the '*const' part).
You could declare the function like this instead: and it would do exactly the same, but the compiler is forced to assume that it can potentially change everything, so no or very little optimising is possible (in and around the code that calls that function - the function itself may be optimised, but it may have been compiled separately and at a different point in time. But now you're compiling your code that *uses* that function and your compiler has no knowledge about what's inside. Thus the declaration hints.)
There's also a bit for the programmer though - if the parameters weren't named 'in' and 'out' it would be difficult to figure out what the parameters are for, in this function for example: Now, if you name them 'source' and 'destination' instead, it's easier.. but in fact it's a given if you see this instead: The above must mean that string1 is the destination, string 2 (completely immutable) must be the source. So in using 'const' correctly there is value for the programmer as well as for the compiler. The compiler needs it, the programmer may not, by using comments and sensible variable namess, but best practice is to do what's also good for the compiler.
Other languages have other ways of providing hints for the compiler, e.g. for when it's probably safe to garbage-collect early, e.g. by using 'undef ($variable);' explicitly in Perl.