Reputation: 1265
In programming languages like Java, C# or PHP we can't use uninitialized variables. This makes sense to me.
C++ dot com states that uninitialized variables have an undetermined value until they are assigned a value for the first time. But for integer case it's 0?
I've noticed we can use it without initializing and the compiler shows no error and the code is executed.
Example:
#include <iostream>
using namespace std;
int main()
{
int a;
char b;
a++; // This works... No error
cout<< a << endl; // Outputs 1
// This is false but also no error...
if(b == '0'){
cout << "equals" << endl;
}
return 0;
}
If I tried to replicate above code in other languages like C#, it gives me compilation error. I can't find anything in the official documentation.
I highly value your help.
Upvotes: 4
Views: 1467
Reputation: 12527
As others have stated it's not always feasible for the compiler to detect if the variable is uninitialized and C and C++ prefer performance in those cases.
However, there are some additional points:
There are dynamic checkers that will detect if any of your test-cases uses an uninitialized variable. That only works if you don't zero-initialize them "just in case".
In C++ you can mix statements and declarations, so instead of
int a,b,c; ... c=2; a=12*c; b=...;
you can write:
...
int c=2;
int a=12*c;
int b=...;
and if you don't modify them further you can add const
as well, and lambdas are also useful for this.
std::optional<...>
. It can avoid some of those 'possibly uninitialized' cases and can detect if you try to access it when uninitialized. But it has a cost.Upvotes: 3
Reputation:
There is no way to "mark" a variable as being uninitialized unless you store an extra bit of information somewhere, or reserve a value in the range of values that the data type covers. Plus every reference to the variable would have to test for uninitializedness.
All of this is completely unacceptable.
Also note that automatic variables are not implicitly initialized to some value (say 0) because this has a cost at run-time, even if the variable is not used.
Upvotes: 3
Reputation: 123566
Anything is possible when your code has undefined behavior.
Correct code does not contain undefined behavior. Using the value of an uninitialized variable is undefined behavior.
The concept of undefined behavior is not unique to C++, but in C++ it is more important than elsewhere because there are so many chances to write wrong code without getting a compiler error.
However, the compiler is your friend. Use it! For example with gcc -Wall -Werror
should be your default to get the error message:
<source>: In function 'int main()':
<source>:9:6: error: 'a' is used uninitialized [-Werror=uninitialized]
9 | a++; // This works... No error
| ~^~
<source>:13:5: error: 'b' is used uninitialized [-Werror=uninitialized]
13 | if(b == '0'){
| ^~
cc1plus: all warnings being treated as errors
Though, not all cases of undefined behavior can be caught by warnings (that can be treated as errors).
C++ dot com states that uninitialized variables have an undetermined value until they are assigned a value for the first time. But for integer case it's 0?
The correct term is indeterminate. As you can see in the above compiler output, there is no difference for your int a;
. When anything can happen then undefined behavior can look like correct behavior, nevertheless it must be fixed.
TL;DR: You cannot use the value of an uninitialized variable. Code that compiles without errors is not necessarily correct.
Upvotes: 4
Reputation: 8783
It isn't feasible or even possible to detect or prove that variable is used uninitialized in all cases. For example:
int a;
if (<complex condition>)
a = 0;
if (<another complex condition>)
a = 1;
++a;
Can there be case when both conditions are false? You wouldn't know, unless you do an extensive analysis of your program. Pointers to variables can be passed, multithreading might be involved, making analysis even harder.
So, the decision was made to trust the programmer and merely declare those UB.
Modern compilers can issue warnings in many cases of uninitialized variable usage, and you should always use maximum warning level.
Upvotes: 5
Reputation: 234885
C++ gives you the ability to shoot yourself in the foot.
Initialising an integral type variable to 0 is a machine instruction typically of the form
REG XOR REG
Its presence is less than satisfactory if you want to initialise it to something else. That's abhorrent to a language that prides itself on being the fastest. Your assertion that integers are initialised to zero is not correct.
The behaviour of using an uninitialised variable in C++ is undefined.
Upvotes: 11