In my method, I declare some variables, including int blockCount;. I call this method more than once. Using the Xcode debugger, I found out that after the second time the method was called, the value of blockCount was set to 364265, while it was set to 2, just a few milliseconds earlier.
It's not a real problem, since I can just set it to 0 or any other number I'd like, but is it bad programming habit to have a certain variable declared over and over again? I'm quite new to programming, and I want to make sure I'm doing things the right way. :)
If you declare a variable but don't provide a value for it, it is considered "uninitialized". An uninitialized variable in C has an "undefined" value -- it's usually garbage, containing whatever happened to be at that address the last time something was written there. Strictly speaking, though, "undefined" means that you should under no circumstances try to use that value. (If you do a search for "nasal demons" this will be explained in quite colorful, and also useful, terms.*)
This variable, being local, is recreated every time the method runs, and thus gets a new actual, though still technically undefined value each pass.
It's generally recommended to not leave variables uninitialized, because the "random" value can cause bugs that are hard to find, and occasionally summon the aforementioned nasal demons. You're not doing anything wrong, but if you're not setting the actual value within a line or two of the declaration, I'd suggest initializing it to 0 or some sensible default:
int blockCount = 0;
*See also: What happens to a declared, uninitialized variable in C? Does it have a value?
Related
After some discussion on the question found here Correct execution of Final routine in Fortran
I thought it will be useful to know when a function with a pointer result is appropriate to use with a normal or a pointer assignment. For example, given this simple function
function pointer_result(this)
implicit none
type(test_type),intent(in) pointer :: this
type(test_type), pointer :: pointer_result
allocate(pointer_result)
end function
I would normally do test=>pointer_result(test), where test has been declared with the pointer attribute. While the normal assignment test=pointer_result(test) is legal it means something different.
What does the normal assignment imply compared to the pointer assignment?
When does it make sense to use one or the other assignment?
A normal assignment
test = pointer_result()
means that the value of the current target of test will be overwritten by the value pointed to by the resulting pointer. If test points to some invalid address (is undefined or null) the program will crash or produce undefined results. The anonymous target allocated by the function will have no pointer to it any more and the memory will be leaked.
There is hardly any legitimate use for this, but it is likely to happen when one makes a typo and writes = instead of =>. It is a very easy one to make and several style guides recommend to never use pointer functions.
What is the difference between these two lines?
Set MyMsg = MyMsg.Move(MyFolder2)
MyMsg.Move(MyFolder2)
The first one works just fine.
The second one usually gives an "Outlook is not responding" error.
The MailItem.Move method returns the MailItem that has been moved. Usually, properties return values and methods don't return anything. But for several methods, the designers decided it would be handy to have a return value, so they made them return a value (or object).
When you assign a method to a variable, any arguments must be in parentheses or you'll get a syntax error. If you call a method without assigning it to a variable (because you don't care what the method returns or it's one of the methods that doesn't return a value), then the arguments must not be in parentheses (kind of).
Parentheses, when used in places that the compiler does not require them, are the equivalent of saying "evaluate this before doing anything else". It's like how you use parentheses in order of operations so you can say "evaluate this addition operation before you do this multiplication even though that's not the normal order".
The (kind of) remark above is because most of the time when you "incorrectly" put parentheses around something, it doesn't matter.
Application.CreateItem 0
and
Application.CreateItem (0)
are the same. The second one evaluates the argument before it passes it to CreateItem, but evaluating a single integer takes no time and has no ill effects. The parentheses aren't necessary because we're not assigning the results to a variable, but they're not really hurting anything either.
In your second example, you're telling the compiler to evaluate the folder, then send it to the Move method. I don't know what evaluating a folder means, but I gather it's not good. It probably does something like create an array of all the objects in that folder, or something equally intensive. When Outlook is not responding, it means you gave it such a big job that it hasn't checked back in with the operating system in a timely fashion.
So: Use parentheses for arguments when it's on the right side of an equal sign. Don't use them when it's not. There are a few exceptions to that rule, but you may never need to know them.
There is no difference between the two (you just ignore the function result) unless you actually use the MyMsg variable afterwards - after the message is moved, you cannot access it anymore.
Use the first version.
Is there any advantage to using a constant (unchangable) than just not changing a variable?
Depending on your language and compiler, a constant may get inlined & optimized when built. Variables will likely eat up stack space even if it never changes.
By making the value constant, the compiler can just substitute it. If you have x / 2, for example, the compiler can compute the value and use that instead of having to emit code to retrieve the value of x and then divide it by 2.
Also, you don't have to worry about accidentally changing the value. For example, in C-like languages you might accidentally type if (x = 2) when you meant if (x == 2) which will change the value of x if it's a variable.
Anyone maintaining your code in the future (including you) won't have to look around to see where (if anywhere) a constant is changed when finding a bug or adding a feature - they'll know right off the bat that it can't be changed.
In some program languages, declaring something to be constant will allow a compiler to make optimizations which would not otherwise be possible. Further, declaring something to be constant can be a useful way of documenting that there are places in the code which might be broken should the value change.
Unfortunately, some programming languages sometimes do evil things with things that are declared constant. For example, in some .net languages, if a value type which is declared read-only is passed by modifiable reference, the compiler will, rather than refusing to allow such an action, instead make a copy and pass that. Such implicit copying will impair efficiency, and may result in unexpected semantics.
Can anyone tell me what the difference is between these 2 lines of code, which one is better to use?
System::String ^MyStr = gcnew System::String(MyStr);
System::String ^MyStr;
Those lines are not equivalent. In the first one, you will get an exception beacuse you're trying to create a String from an uninitialized tracking handle (MyStr). In the second one, MyStr is declared, not defined, it points to garbage and will throw an exception if you attempt to use it. Which one you should use depends on the rest of the code
The second one creates a new handle variable. If it's a local variable, then as #dario_ramos says, it's uninitialized, and your program will likely crash if you try to use the handle before assigning it. If it's a member variable or global, then it will be nullptr.
The first one is similar, although it can only be used for locals or globals (member variables use the ctor-initializer syntax in C++/CLI just like plain C++), and does exactly what you're not permitted to do. It reads the brand new uninitialized handle and passes it to the System::String constructor. If by chance the constructor finishes, a handle to the newly constructed String will be placed into the variable as part of initialization. But because the constructor is trying to make a copy of random garbage (if it's a local) or nullptr (if a global), most likely it will simply crash.
It's a bad idea to use the value of any variable in its own initializer (sometimes you need to use the address, never the value).
Today I discovered that something I had assumed about VB.NET for many years was not true (worrying!). I assumed that a variable declared within a loop had a lifetime of the iteration it was declared in, but in fact it seems it has a lifetime of the whole procedure.
For example:
For i As Integer = 0 To 1
Dim var1 As Boolean
Console.WriteLine(var1.ToString())
var1 = True
Console.WriteLine(var1.ToString())
Next
Console.ReadKey()
I had assumed an output of False, True, False, True but instead it is actually False, True, True, True.
In C# the equivalent code would not compile as you would get a compile time error of Error "Use of unassigned local variable 'var1'".
I realise there are many ways to fix this and that best practice would be to declare the variable outside of the loop and reset it at the beginning of every loop through.
I find this behaviour so counter-intuitive to me that I would like at least a compile time warning in VB.NET when/if I do this. (I could also then set this on any projects I already have and get warning that would allow me to check that my assumptions aren't causing errors).
Does anyone know how/if I can get this to generate a compile time warning in VB.NET? Am I the only one that finds this counter-intuitive?
We'll have to work on fixing your intuition because getting an error out of the compiler is not an option. It is partially implemented, you can get this warning:
error BC42104: Variable 'mumble' is used before it has been assigned a value. A null reference exception could result at runtime.
And elevate it from a warning to an error with Project + Properties, Compile tab. However, as the warning message indicates, this is only supported for reference type references, it won't budge for a variable of a value type.
Okay, intuition. If the runtime would implement your desired behavior then it would have to allocate a new variable for each iteration of the loop. Which implies that the number of local variables is bounded only by the number of iterations. This is very wasteful and a very easy trigger for StackOverflowException. The JIT compiler doesn't do this, it re-uses the variable. This happens in C# as well, minus the option of letting you not initialize the value explicitly of course.
Fwiw: I very much agree with you that this is unhelpful behavior. You'll probably find receptive ears at connect.microsoft.com, post your feature request there and the VB.NET team will see it. There has been strong backing from customers as well as within MSFT to make VB.NET and C# feature comparable. If you post a link to your feedback report then I'll be happy to vote it up.