DON'T USE bits/stdc++.h

Great. Thanks everyone for looking into this. Also, Can I now use the header bits/stdc++.h blindly ignoring these links (https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) as long as the compiler supports it?

Yes, you can.

1 Like

There is no issue with bits/stdc++ for purpose of CP since you don’t need to worry about the compile time :stuck_out_tongue:

1 Like

Considering people are talking about undefined behavior I might as well add my 2 cents.

It’s worth noting that even though something is undefined behavior, the result need not be random at all. It can be perfectly consistent, but you can’t assume anything about the behavior.

One really interesting fact is that compilers can (ab)use undefined behavior to optimize code. One simple example (not my code, stolen from a youtube comment)

#include<iostream>

using namespace std;

int main()
{
    for (int i = 0; i < 10; ++i)
        cout << i*1000000000 << endl;
}

How many lines do you expect this to print?

  • With no optimization it’s as you expect, 10 lines.

  • With optimization (at least for my compiler) the loop runs forever.

I can recommend you to stop reading after this sentence try to reason about why this is, and look at the helpful warning the compiler gives you.


The compiler very helpfully warns you if you compile with optimization:

ub.cpp: In function ‘int main()’:
ub.cpp:7:19: warning: iteration 3 invokes undefined behavior [-Waggressive-loop-optimizations]
         cout << i*1000000000 << endl;
                   ^~~~~~~~~~
ub.cpp:6:23: note: within this loop
     for (int i = 0; i < 10; ++i) {

So what’s going on? The problem is signed integer overflow, which is undefined behavior. But why does that produce an infinite loop?

The compiler knows that signed integers are not allowed to overflow. This puts a constraint on i, namely that i < 3. But in that case the loop condition i < 10 is always true, so why check that? The compiler happily optimizes that check away, and we end up with an infinite loop.

4 Likes

@algmyr So basically, this varies from compiler to compiler as the compilers are not set to produce results for a false(invoking undefined behaviour) code…right?

Behavior may or may not be different in different compilers, or even for the same code snippet in different circumstances using the same compiler. Point is you can’t really assume anything as soon as you introduce UB into the program.

In the case you had, compiling with “-fstack-protector-all -fsanitize=address” and testing against a few cases would probably have showed you that something was wrong. Try running your old code with the flags I mentioned on the case:

1
2
1 1