How is this possible in the following program. total should be equal to 1 million.
1 2 3 4 5 6 7 8 9 10 11 12 13
#include <iostream>
usingnamespace std;
int main() {
constint n= 1e6;
bool ar[n];
int one=0, zero=0;
for(int i=0; i<n; i++){
if(ar[i]==0) zero++;
if(ar[i]==1) one++;
}
cout << "res: " << "one = " << one << ", zero= " << zero << ", total = " << one+zero;
}
output gcc in my pc
res: one = 123, zero= 997792, total = 997915
--------------------------------
Process exited after 0.0214 seconds with return value 0
Press any key to continue . . .
ar's values are not initialized, but on lines 9 and 10, you are using their uninitialized values. This is undefined behavior, and there's no point in analyzing the program further (except for learning purposes, in which case you'd have to look at the assembly to see what the compiler is doing).
while that is true, if you change it slightly it will work regardless, treating the uninitialized array as if it were randomly initialized, which it is in practice on all compilers.
option one, is count true/false:
zero += ar[i]==false; //still counts zeros
one += ar[i] != false ; //this counts not only 1s but anything not zero
or option 2 is to count a third category, neither zero nor 1, and the 3 sums will be the right value.
or option 3 is init all the values to 0 or 1
You are not wrong! :)
The gold standard of no undefined behavior is important, and always a concern in serious code. That makes using ar without dumping something into it wrong.
So, backing up to be precise: all 3 options SHOULD initialize the array EVEN IF it works without it (which it will, on every compiler I know of, as long as its not running fail on strict language settings, which the OP isn't apparently doing).
Options 1 and 2 are still valid for various scenarios though: option 1 counts differently using the 0 is false, else true logic that C++ allows and has merits for some problems. Option 2 counts 1 and 0 and everything else, so you get your pure totals by value if the initialize isn't just 0 and 1 . Option 3 (doing nothing but adding an initialize) also works fine, assuming it inits 0 and 1 only.
... EVEN IF it works without it (which it will, on every compiler I know of ...
Okay, let's test this...
Note that the total is often larger than the number of elements in the array.
You might get different numbers if you rerun the tests.
I cherry picked optimization levels that gave wrong results.
now that is interesting. I concede, this no longer works. Something in modern optimizations is mistranslating a simple read memory, add 1 or 0 to result ... as soon as you change it to {} initialized it changes the assembly of the loop to lea out the right memory location. I was wrong, and I really did not expect the loop body to change based off the array's initial condition.
if you put it back to pure if conditions, it gives 1 million total.
the problem is somewhere in converting true to 1 and false to 0 in the addition, but I don't see it right this min.
Edit: I see the issue:
it wants this:
zero += (bool)ar[i];
one += !((bool)ar[i]);
I was casually having a look at this question the other day and today I came across a GameDev forum topic in which this same example is shown. This question immediately came up to my mind. Are you trying to understand the difference between const and constexpr, by any chance?