weird program output

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>
using namespace std;

int main() {
	const int 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 . . .

output at https://rextester.com/l/cpp_online_compiler_clang
Compilation time: 0.52 sec, absolute running time: 0.14 sec, cpu time: 0.01 sec, memory peak: 5 Mb, absolute service time: 0,67 sec
res: one = 225584, zero= 1223967, total = 1449551
although their gcc shows correct total. cpp.sh also shows correct total.
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
Last edited on
Jonnin, lucky for you there is no downvote feature. ;-)

The correct solution is to initialize the array (i.e. option 3).
Last edited on
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.
Last edited on
jonnin wrote:
... 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.

The original:

https://godbolt.org/z/q1qjsrWY8 GCC -O0
res: one = 29, zero= 997939, total = 997968

https://godbolt.org/z/ehT773v4x Clang -O1
res: one = 237394, zero= 997922, total = 1235316


Option 1:

https://godbolt.org/z/h8fKaGKq3 GCC -O2
res: one = 232591, zero= 1230377, total = 1462968

https://godbolt.org/z/G5EsM9od3 Clang -O2
res: one = 268740, zero= 997875, total = 1266615


Option 2:

https://godbolt.org/z/aKhvxWh74 Clang -O1 (using 3 ifs)
res: one = 256370, zero= 997982, other= 0, total = 1254352

https://godbolt.org/z/Tj7McqGW6 Clang -O3 (using if/else if/else)
res: one = 258958, zero= 997908, other= 0, total = 1256866
Last edited on
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]);

https://godbolt.org/z/ss5e87cbM

Last edited on
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?
Registered users can post here. Sign in or register to post.