Bellow is a simple program that is suppose to check a certain text file to see if a word, in this case a name, is present in it.
I keep getting a pop up stating "The variable 'NamePresent' is being used without being initialized." Isn't NamePresent initialized as a bool?
#include <fstream>
#include <iostream>
#include <string>
int main()
{
std::ifstream NameFile("Names.txt");
std::string Name;
bool NamePresent;
std::cin >> Name;
while(NameFile >> Name)
{
if(NamePresent == true)
{
std::cout << "This works!" << std::endl;
}
if(NamePresent == false)
{
std::cout << "Nope!" << std::endl;
}
}
return 0;
}
No, it is declared as a bool. You still need to assign it a value of either true/false:
bool NamePresent = false;
"Initialized" means initialized with a value.
bool NamePresent = false;
In your code above, it is declared as a bool, but not initialized. Also, no other statement in your code assigns a value to NamePresent (but presumably you're working on that).
Any decent compiler would give us the warning if program tries to use the variable which is not initialized(uninitialized).
test.cpp: In function ‘int main()’: test.cpp:15:9: warning:
‘NamePresent’ may be used uninitialized in this function
[-Wmaybe-uninitialized]
if(NamePresent == true)
^
You should pay attention to compiler messages carefully.
There are 4 important moments in the life of a variable:
Declaration
In this step you inform the compiler about the variable type. This is required so that the compiler knows how to interpret the data in memory, for example.
Definition
This is the "birth" of the variable. If in the declaration you specified its name and type, here you instruct the compiler to allocate memory for it. Note that a statement such as int a; is both a declaration and a definition, as it introduces a new name (a) and allocates memory for an int variable.
Initialization
When a variable is defined, some memory is reserved for it. The initial value of the variable is the content of that memory, which can be anything (this is usually known as garbage). So you need to assign the first useful value to your variable. Of course, you can use it without initialize it to a value, but this is error prone, as you cannot rely on the value of that variable. The compiler knows this and gives you a warning. Note that you will get also warnings if you initialize a variable in a loop or a conditional branch, as the condition might not be true or the loop might not be executed.
Death
Although this point has no real use for your question, it is worth remembering. A variable dies when it goes out of scope (usually when the instruction block where it has been defined ends, if it is a local variable, and when the program ends if it is a global variable).
Related
So I have been working on a question and this think stumbled upon me. When I declare a variable outside the main function, the program works correctly, that is it reaches the else case of "Friendship is magic" but if the variable is declared inside it returns Chris instead of Friendship statement.
int mis, chr;
int main() {
int a, n, m;
cin >> a;
for (int i = 0; i < a; i++) {
//code here
}
if(mis > chr)
cout << "Mishka";
else if(chr > mis)
cout << "Chris";
else
cout << "Friendship is magic!^^";
}
The input that I am using makes the value of chr and mis equal so it should be evaluating to the else statement but instead it just stops at else if.
"With great power (provided by C++) there must also come great responsibility"
And
"With uninitialized variables comes the undefined behavior"
Variables that are declared at global scope are being initialized by the compiler. However, the variables defined inside any function (i.e, having automatic storage) may contain garbage values (that could be different in each invocation of the program). I recommend always initializing your variables to some value.
int main()
{
int mis = 0, chr = 0;
// ...
return 0;
}
Let's come to your program now:
When I declare a variable outside the main function, the program works correctly, that is it reaches the else case of "Friendship is magic"
It is happening because the variables (on which your if ladder dependent) are being initialized to 0. Since, both variables have same value (0), the else part of the if statement is being executed.
but if the variable is declared inside it returns Chris instead of Friendship statement.
It's a perfect example of undefined behavior. If they are defined inside your function, they will be holding some garbage value and that might not be equal. Hence, what you are observing is an undefined behavior and you might get different results in different machines or even sometimes in a same machine.
I tried your code and it works the same for me in both cases.
So, I would say it changes with editor to editor and always initialize the variable before using it.
Otherwise, we might face the same problem as you face. As it initializes the variables with garbage values.
While upgrading a legacy project to VS2015, I noticed there were a lot of errors where a local variable was redefined inside a function for example.
void fun()
{
int count = applesCount();
cout << "Apples cost= " << count * 1.25;
for (int bag=0; bag<5;bag++)
{
int count = orangesCount(bag);
cout << "Oranges cost = " << count * 0.75;
}
}
The error/warning message by compiler is:
declaration of 'count' hides previous local declaration
I know it is obviously not a good practice to use the same name for variable count but can the compiler really mess things up as well or generally they deal this situation rather gracefully?
Is it worth it to change and fix the variable names or is unlikely to cause any harm and is low or no risk?
I noticed there were a lot of errors where a local variable was redefined inside a function for example.
You are not demonstrating redefining here. You show an example of variable shadowing.
Variable shadowing is not an error syntactically. It is valid and well defined. However, if your intention was to use the variable from the outer scope, then you could consider it a logical error.
but can the compiler really mess things up
No.
The problem with shadowing is that it can be hard to keep track of for the programmer. It is trivial for the compiler. You can find plenty of questions on this very site, stemming from confusion caused by shadowed variables.
It is not too difficult to grok which expression uses which variable in this small function, but imagine the function being dozens of lines and several nested and sequential blocks. If the function is long enough that you cannot see all the different definitions in different scopes at a glance, you are likely to make a misinterpretation.
declaration of 'count' hides previous local declaration
This is a somewhat useful compiler warning. You haven't run out of names, so why not give a unique name for all local variables in the function? However, there is no need to treat this warning as an error. It is merely a suggestion to improve the readability of your program.
In this particular example, you don't need the count in the outer scope after the inner scope opens, so you might as well reuse one variable for both counts.
Is it worth it to change and fix the variable names
Depends on whether you value more short term workload versus long term. Changing the code to use unique, descriptive local variable names is "extra" work now, but every time someone has to understand the program later, unnecessary shadowing will increase the mental challenge.
IMHO, bad coding practice. Hard to maintain and read.
The compiler can discern between the outer variable and the internal variable.
With a good vocabulary (and a thesaurus), one doesn't need to use the same variable names.
Shadowing a variable (which is what this is) has completely well defined semantics, so the compiler won't mess it up. It will do exactly what it has been told, with well defined result.
The problem is (as is often the case) with the humans. It is very easy to make mistakes when reading and modifying the code. If one is not very careful it can be tricky to keep track of which variable with a given name is being referenced and it's easy to make mistakes where you think you are modifying one but in reality you are modifying another.
So, the compiler is fine, the programmer is the problem.
In my experience, compilers usually handle this issue pretty gracefully.
However, it is definitely bad practice, and unless you have a really compelling reason to do so, you should either reuse the old variable (if it logically makes sense to do so), or declare a [differently-named] new variable.
Can be very bad:
Consider this
std::vector<int> indices(100);
if (true) {
std::vector<int> indices(100);
std::iota(indices.begin(), indices.end(), 0);
}
// Now indices will be an all-0 vector instead of the an arithmetic progression!
In Visual Studio, compiling with Warning Level4 /W4 will output a warning even when disambiguating by prefixing with the implicit this pointer, like in this->Count:
warning C4458: declaration of 'Count' hides class member
Although the compiler rarely makes a mistake with the values, shadowing can be abused and get confusing overtime.
Below is an example of shadowing the Count member variable which should be avoided:
From the Unreal Coding Standard document.
class FSomeClass
{
public:
void Func(const int32 Count)
{
for (int32 Count = 0; Count != 10; ++Count)
{
// Use Count
}
}
private:
int32 Count;
}
One option to dealing with this would adding a prefix to the incoming argument name when shadowing occurs, like so:
class FSomeClass
{
public:
void Func(const int32 InCount)
{
Count = InCount;
for (int32 Counter = 0; Counter != 10; ++Counter)
{
// Use Count
}
}
private:
int32 Count;
}
When using RAII resources it may actually simplify the code to shadow variables and not create new variable names.
An example, a simple logger which writes to stdout when entering and leaving a block:
class LogScope {
private:
std::string functionName;
uint32_t lineNo;
public:
LogScope(std::string _functionName, uint32_t _lineNo) :
functionName(_functionName), lineNo(_lineNo) {
std::cout << "Entering scope in " << functionName << " starting line " << lineNo << std::endl;
};
~LogScope(void) {
std:: cout << "Exiting scope in " << functionName << " starting line " << lineNo << std::endl;
};
};
It could be used like:
void someFunction() { // First scope here.
LogScope logScope(__FUNCTION__, __LINE__);
// some code...
// A new block.
// There is really no need to define a new name for LogScope.
{
LogScope logScope(__FUNCTION__, __LINE__);
// some code...
}
}
Having said that, normally it is good practice, not to reuse your variable names.
Zar,
The compiler will handle this situation fine. In your example, the count variable is defined in two different scopes '{}'. Due to the scope of the variable, the assembly language will refer to two different addresses on the stack. The first 'count' might be the stack point, SP-8, while the inner count might be SP-4. Once transformed into an address the name is irrelevant.
I would not generally change working code for stylistic reasons. If the code is a mess then you run the risk of breaking it. Usually messy code doesn't have any good tests so it hard to know if you broke it.
If you need to enhance the code then certainly tidy up.
--Matt
http://en.cppreference.com/w/cpp/language/storage_duration
Static local variables
Static variables declared at block scope are initialized the first
time control passes through their declaration (unless their
initialization is zero- or constant-initialization, which can be
performed before the block is first entered). On all further calls,
the declaration is skipped.
What is the meaning of 'static' in this quote? Is it:
static storage duration. The storage for the object is allocated when
the program begins and deallocated when the program ends.
If so, then it doesn't explain what happens to int k; in the main or any other function in terms of initialization, because k is not a static variable (it doesn't get allocated when the program begins and deallocated when the program ends - wait a second, you might say that the main function starts running when the program begins and returns when the program ends, but that's not how it works I guess).
In the main function:
int k;
k++;
results in an error: uninitialized local variable 'k' used.
So if k above is not a static local variable, could you give an example of such variables?
And could anyone tell me why the following code compiles and runs without any issues, even though k is not initialized?
Given a function with no body:
void foo(int* number) { }
And calling it like this in main:
int k;
foo(&k);
k++;
It now compiles and runs with no problems, but the value of k is -858993459. The compiler didn't like the fact I attempted to increment it without initiation, but passing it to foo caused that the compiler forgot about it. Why?
Probably depends on your compiler implementation.
I guess the compiler sees that you variable is passed to a function in a non-const way, so the function can potentially modify/initialize the value of k.
Your compiler doesn't dig into the function to extrapolate the logic, so it let you compile the code.
EDIT : I don't get the same behaviour with this online compier : http://cpp.sh/9axqz
But the compilation warning disapears as soon as I do something with the number in the function.
A static local variable is something like this:
void example() {
static int i = 0; // a static local variable
int j = 0; // not static
// ...
}
Builtin types such as int are not automatically initialized. Therefore you may get a warning when you try to read from that variable before having set it to something meaningful because it can hold just about anything.
Just because your particular compiler no longer gave you a warning does not mean that your variable is initialized properly. As a rule of thumb you should always explicitly initialize your variables to avoid accidentally reading from it without having set it first:
int i; // not initialized
int j = 0; // explicitly set to 0
Here is a link to the C++ Core Guidelines on the topic of initialization: https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#es20-always-initialize-an-object, it may be worth a read.
A static variable can be defined like this:
int nextIndex()
{
static int index = -1;
return ++index;
}
So when you first call this function the static variable index will be initialized with -1;. The next line will increase index by 1 and return the result.
All subsequent calls of nextIndex will only execute the return ++index; part and skip the initialization.
Also static varibales are automatically initialized with zero if not implemented different.
So if you change above function to
int nextIndex()
{
static int index;
return ++index;
}
the first value it returns will be one. Also the first call won't initialize the index, but it will be initialized as soon as your program starts.
I compiled the following code using g++
#include <iostream>
int main()
{
double res;
std::cout << res << std::endl;
return 0;
}
That gave the following result
g++ foo.c
./a.out
0
But after a small change
#include <iostream>
int main()
{
std::string input;
double res;
std::cout << res << std::endl;
return 0;
}
It became
g++ foo.c
./a.out
2.0734e-317
Why are the results different and why the number 2.0734e-317?
Your code invokes undefined behaviour. Since automatic variables of built-in types are not deafult-initialized unless specifically aksed, value for variable res is undefined in your code. It can be anything.
Why you have different value their based on different code structure is understandable - since no one is setting the value for the variable, you are left with whatever is left in the stack memory after previous calls. Pure random.
In particular, in the former example, the stack memory is not used at all before you declare your res variable. As a result, you use untouched stack memory, which is 0 initialize. In the latter case, you have already defined string variable, and called it's constructor. Constructor used stack memory for it's own purpose, and left those values there. Now the res variable is constructed in used stack memory, and you see some random values there.
It's arbitrary.
You did not initialise your variable. It has an unspecified value.
Therefore, reading its "value" has undefined behaviour. Anything can happen.
Not only can you get any value (due to internal assumptions that you cannot rationalise about from outside of the black box of the compiler implementation), but you could also/instead open a black hole or kill my cat, and I would not be terribly happy about either of those outcomes.
You are outputting an uninitialized variable. So it's value can be anything.
For some reason in my c++ code, int i= 0 is not working. In debug mode, it stores 1024 into i after it goes out of scope. When I try to declare it to 0, it doesn't work. i is not a global variable.
void CCurrent::findPeaks()//this checks for peaks in the FFT
{
int localPeakIndx[256]={};
int j=0;
for(int i=0;i<DATASIZE/2;i++)
{
if(magnitude[i]>m_currentValues.AverageMagnitude*3) {
localPeakIndx[j]=i;
j++;
}
}
//i should be out of scope
int startIndx;
int endIndx;
int i = 0;//why does it equal 1024?????? debug*
It is not clear what you mean by "int i= 0 is not working" and "it stores 1024 into i after it goes out of scope". That description is unrealistic and most likely does not take place. After int i = 0 the value of i will be seen as 0, not as 1024.
What you have to keep in mind in this case is that your program has two i variables: one local to for cycle and one declared further down in the surrounding block. These are two different, completely unrelated variables.
Now, MS Visual Studio debugger will show you the values of all variables declared in the current block, even if the execution has not yet reached their point of declaration. Expectedly, variables whose declaration (and initialization) point has not been reached yet are shown with indeterminate (uninitialized) values.
Apparently, this is exactly what happens in your case. Your are looking at the value of outer i before its point of declaration and initialization. Even though name i is not yet visible immediately after the for cycle from the language point of view, the debugger will nevertheless give you "early access" to the outer i. The garbage value of that i at that point just happened to be 1024 in your experiment.
Note that there's certain definitive logic in this behavior. In general case it is not correct to assume that a local object does not exist above the point of its declaration. Being located above the point of declaration in spatial terms does not necessarily mean being located before the point of declaration in temporal terms, which becomes clear once you start using such beautiful feature of the language as goto.
For example, this piece of code
{
int *p = NULL;
above:
if (p != NULL) {
std::cout << *p << std::endl;
goto out;
}
int i = 10;
p = &i;
goto above;
out:;
}
is legal and has perfectly defined behavior. It supposed to output the valid initialized value of i through a valid pointer p, even though the output takes place above the i's point of declaration. I.e. it is possible to end up in the situation when the current execution point is located above the object declaration, yet the object already exists and holds a determinate value. To help you with debugging in such situations the debugger allows you to see the values of all objects that may potentially exist at that point, which includes all objects declared in the current block. In general case the debugger does not know which objects formally exist already and which do not, so it just lets you see everything.
Just a small refinement of what was already said:
The "outer i" is given space on the stack along with all other local variables when the function is entered.
Since the "outer i" hasn't been given a value before the end of the for loop, the debugger is looking on the stack where the value for i ought to be, and showing you what happens to be there.
This comes from the fact that local variables are not initialized.
I bet if you tried to access i from C before the declaration, the compiler would tag that as an error. But the debugger doesn't have such scruples.